
#include "sal.h"
#include "dal.h"
#include "usw/include/drv_enum.h"
#include "usw/include/drv_common.h"
#include "drv_api.h"
#include "usw/include/drv_io.h"
#include "usw/include/drv_ftm.h"
#include "usw/include/drv_app.h"
#include "usw/include/drv_sdb.h"

#define DRV_MEM_SUB_ID(lchip, mem_id)       (DRV_MEM_INFO(lchip, mem_id).sub_id)
#define DRV_MEM_SUB_ID_BASE(lchip, mem_id)  (DRV_MEM_INFO(lchip, mem_id).sub_id_base)

#define DRV_SDB_TBL_DYNAMIC 0
#define DRV_SDB_TBL_TCAM_AD 1
#define DRV_SDB_TBL_SNAKE   2
#define DRV_SDB_TBL_DP      3

#define DRV_SDB_INIT_CHECK(lchip)   {\
    if (lchip >= DRV_MAX_CHIP_NUM || !p_drv_master[lchip] || !g_sdb_master[lchip]) {\
        return DRV_E_NOT_INIT;\
    }\
}

#define DRV_SDB_DUMP(fmt, arg...)  sal_printf(fmt, ##arg)
#define DRV_SDB_DUMP_FILE(pf, FMT, arg...)  (pf ? sal_fprintf(pf, FMT, ##arg) : sal_printf(FMT, ##arg))

enum drv_ser_db_tcam_key_action_e
{
    DRV_SDB_TCAM_KEY_REMOVE,
    DRV_SDB_TCAM_KEY_ADD,
    DRV_SDB_TCAM_KEY_ACTION_MAX
};
typedef enum drv_ser_db_tcam_key_action_e drv_ser_db_tcam_key_action_t;
struct drv_sdb_mem_hdr_s
{
    uint32 wb_version;
#if (SDB_TIMESTAMP == SDB_MODE)
    uint8  init_done;
    uint8  rsv[3];
#endif
};
typedef struct drv_sdb_mem_hdr_s drv_sdb_mem_hdr_t;

struct drv_sdb_reset_hw_register_s
{
    uint32 tbl_id;
    uint32 fld_id;
    uint32 value;
    uint32 old_value;
    uint8  type;  /*0:set before reset hw; 1:set before reset hw but recover after dynamic tbl restore;*/
};
typedef struct drv_sdb_reset_hw_register_s drv_sdb_reset_hw_register_t;

drv_sdb_reset_hw_register_t drv_sdb_reset_hw_register[] =
{
    {MucSupMiscCtl0_t, MucSupMiscCtl0_mcuSupDataMemEccCorrectDis_f, 1, 0, 0},
    {MucSupMiscCtl0_t, MucSupMiscCtl0_mcuSupDataMemEccDetectDis_f,  1, 0, 0},
    {MucSupMiscCtl0_t, MucSupMiscCtl0_mcuSupProgMemEccCorrectDis_f, 1, 0, 0},
    {MucSupMiscCtl0_t, MucSupMiscCtl0_mcuSupProgMemEccDetectDis_f,  1, 0, 0},
    {MucSupMiscCtl1_t, MucSupMiscCtl1_mcuSupDataMemEccCorrectDis_f, 1, 0, 0},
    {MucSupMiscCtl1_t, MucSupMiscCtl1_mcuSupDataMemEccDetectDis_f,  1, 0, 0},
    {MucSupMiscCtl1_t, MucSupMiscCtl1_mcuSupProgMemEccCorrectDis_f, 1, 0, 0},
    {MucSupMiscCtl1_t, MucSupMiscCtl1_mcuSupProgMemEccDetectDis_f,  1, 0, 0},

    {OamUpdateCtl_t, OamUpdateCtl_updEn_f,           0, 0, 1},
    {OamUpdateCtl_t, OamUpdateCtl_bfdUpdEn_f,        0, 0, 1},
    {IpeAgingCtl_t,  IpeAgingCtl_hwAgingEn_f,        0, 0, 1},
    {IpeAgingCtl_t,  IpeAgingCtl_gTimmer_2_agingInterval_f, 0x00069271, 0, 1},
    {IpeAgingCtl_t,  IpeAgingCtl_gTimmer_2_scanEn_f, 0, 0, 1},
    {IpePolicing0EngineCtl_t,  IpePolicing0EngineCtl_refreshEn_f, 0, 0, 1},
    {IpePolicing1EngineCtl_t,  IpePolicing1EngineCtl_refreshEn_f, 0, 0, 1},
    {EpePolicing0EngineCtl_t,  EpePolicing0EngineCtl_refreshEn_f, 0, 0, 1},
    {EpePolicing1EngineCtl_t,  EpePolicing1EngineCtl_refreshEn_f, 0, 0, 1},
    {IpfixAgingTimerCtl_t,     IpfixAgingTimerCtl_agingUpdEn_f,   0, 0, 1},
    {IpfixAgingTimerCtl_t,     IpfixAgingTimerCtl_cpuAgingEn_f,   0, 0, 1},
    {SupIntrCtl_t,  SupIntrCtl_funcIntrEn_f,  0, 0, 1},
    {SupIntrCtl_t,  SupIntrCtl_interruptEn_f, 0, 0, 1},
    {SupIntrCtl_t,  SupIntrCtl_padIntrEn_f,   0, 0, 1},
    {SupIntrCtl_t,  SupIntrCtl_pcieIntrEn_f,  0, 0, 1},
    {SupIntrCtl_t,  SupIntrCtl_socIntrEn_f,   0, 0, 1},
    {MacLimitSystem_t, MacLimitSystem_dynamicMaxCount_f, 0, 0, 1},
    {MacLimitSystem_t, MacLimitSystem_profileMaxCount_f, 0, 0, 1},
    {IpeStormCtl0EngineCtl_t, IpeStormCtl0EngineCtl_refreshEn_f, 0, 0, 1},
    {IpeStormCtl1EngineCtl_t, IpeStormCtl1EngineCtl_refreshEn_f, 0, 0, 1},
    {IpeCoPPEngineCtl_t, IpeCoPPEngineCtl_ipeCoPPEngineCtlRefreshEn_f, 0, 0, 1},
    {EpeCoPPEngineCtl_t, EpeCoPPEngineCtl_refreshEn_f, 0, 0, 1}
};

char* drv_sdb_type_str[] = {
    "DIS", "PERF", "ALL"
};

#define DRV_SDB_ACC_TBL_MIN_SIZE      12
#define DRV_SDB_MALLOC_CPU_MEM_SIZE   (24*1024)  /*byte,must 2^n aline*/
#define DRV_SDB_MALLOC_DMA_MEM_SIZE   (48*1024)  /*byte*/
#define DRV_SDB_FLOW_TCAM_RAM_SZ      (2048)
#define DRV_SDB_LPM_TCAM_RAM_SZ       (1024)
#define DRV_SDB_CID_TCAM_RAM_SZ       (128)
#define DRV_SDB_ENQ_TCAM_RAM_SZ       (256)
#define DRV_SDB_TOTAL_SRAM_SZ(lchip)  (((p_drv_master[lchip]->dev_type >= DRV_TSINGMA_MX)?20:9)<<20)
#define DRV_SDB_WB_RELOADING(lchip)  (p_drv_master[lchip]->wb_status == DRV_WB_STATUS_RELOADING)
#define DRV_SDB_IF_CONTINUE(condition)  \
    if (condition)  {\
        continue;\
    }
#define DRV_SDB_MAX_DMA_SIZE(lchip) ((p_drv_master[lchip]->dev_type >= DRV_TSINGMA_MX)? 512*1024:16*1024)
extern dal_op_t g_dal_op;
extern int32 dal_get_chip_number(uint8* p_num);
extern int32 drv_usw_ftm_get_mplshash_mode(uint8 lchip, uint8* is_mpls);
extern int32
drv_usw_chip_read_sram_entry(uint8 lchip, uintptr addr, uint32* data, int32 len);
extern uint32
drv_usw_ftm_memid_2_table(uint8 lchip, uint32 mem_id);
extern int32
drv_usw_ftm_get_sram_tbl_id(uint8 lchip, uint32 sram_type, uint32* p_sram_tbl_id, uint8* p_share_num, uint8* p_per_tbl_entry_num);
int32
_drv_sdb_check_per_table(uint8 lchip, uint32 tbl_id, uint8 flag, sal_file_t pf);

drv_sdb_t* g_sdb_master[DRV_MAX_CHIP_NUM] = {NULL};

int32 drv_sdb_op_none(uint8 lchip, tbls_id_t tbl_id, uint32 index, void* p_data)
{
    return DRV_E_NONE;
}

/*rewrite only rewrite to phy-memory.It is
unnessary to rewrite backup-data,because that
backup-data only can be rewrite when drv-io be called*/
int32
drv_sdb_rewrite_tcam(uint8 lchip, uint8 mem_id, uint8 mem_type, uint8 mem_order, uint32 entry_idx, void* p_data)
{

#if 0
    uint8 action = 0;
    drv_ds_t ds;
    /*uint8 start_mem_id = 0;*/
    tbl_entry_t* p_tbl_entry = (tbl_entry_t*)p_data;

    action = (p_tbl_entry->data_entry == NULL) ? DRV_SDB_TCAM_KEY_REMOVE : DRV_SDB_TCAM_KEY_ADD;
    /*start_mem_id = mem_id - mem_order;*/

    sal_memset(ds, 0, sizeof(drv_ds_t));
    if (DRV_SDB_TCAM_KEY_REMOVE == action)
    {
        if (mem_type == DRV_FTM_MEM_TCAM_FLOW_KEY)
        {
            drv_usw_chip_remove_tcam_entry(lchip, DRV_IO_TCAM_TYPE_FLOW, mem_order, entry_idx, (uint8*)ds);
        }
        /*lpm tcam*/
        else if (mem_type == DRV_FTM_MEM_TCAM_LPM_KEY)
        {
            drv_sdb_unmap_lpm_tcam(lchip, &mem_id, &mem_order, (uint16*)&entry_idx);/*12 to 3 map*/
            drv_usw_chip_remove_tcam_entry(lchip, DRV_IO_TCAM_TYPE_LPM, mem_order, entry_idx, (uint8*)ds);

        }
        /*cid tcam*/
        else if (mem_type == DRV_FTM_MEM_TCAM_CID_KEY)
        {
            drv_usw_chip_remove_tcam_entry(lchip, DRV_IO_TCAM_TYPE_CID, 0, entry_idx, (uint8*)ds);

        }
        /*enque tcam*/
        else if (mem_type == DRV_FTM_MEM_TCAM_QUEUE_KEY)
        {
            drv_usw_chip_remove_tcam_entry(lchip, DRV_IO_TCAM_TYPE_QUE, 0, entry_idx, (uint8*)ds);
        }
        else
        {
            return DRV_E_INVAILD_TYPE;
        }

    }
    else/*add*/
    {
        if (mem_type == DRV_FTM_MEM_TCAM_FLOW_KEY)
        {
            drv_usw_chip_write_tcam_entry(lchip, DRV_IO_TCAM_TYPE_FLOW, mem_order, entry_idx, p_tbl_entry->data_entry, p_tbl_entry->mask_entry, (uint8*)ds);
        }
        /*lpm tcam*/
        else if (mem_type == DRV_FTM_MEM_TCAM_LPM_KEY)
        {
            drv_sdb_unmap_lpm_tcam(lchip, &mem_id, &mem_order, (uint16*)&entry_idx);/*12 to 3 map*/
            drv_usw_chip_write_tcam_entry(lchip, DRV_IO_TCAM_TYPE_LPM, mem_order, entry_idx, p_tbl_entry->data_entry, p_tbl_entry->mask_entry, (uint8*)ds);
        }
        /*cid tcam*/
        else if (mem_type == DRV_FTM_MEM_TCAM_CID_KEY)
        {
            drv_usw_chip_write_tcam_entry(lchip, DRV_IO_TCAM_TYPE_CID, 0, entry_idx, p_tbl_entry->data_entry, p_tbl_entry->mask_entry, (uint8*)ds);
        }
        /*enque tcam*/
        else if (mem_type == DRV_FTM_MEM_TCAM_QUEUE_KEY)
        {
            drv_usw_chip_write_tcam_entry(lchip, DRV_IO_TCAM_TYPE_QUE, 0, entry_idx, p_tbl_entry->data_entry, p_tbl_entry->mask_entry, (uint8*)ds);
        }
        else
        {
            return DRV_E_INVAILD_TYPE;
        }
    }
    #endif

    return DRV_E_NONE;
}

int32
drv_sdb_get_mem_id_info(uint8 lchip, uint8 mem_id, uint8* p_order , uint8* p_type)
{
    int32 ret = 0;
    drv_ftm_mem_info_t mem_info;

    sal_memset(&mem_info, 0, sizeof(drv_ftm_mem_info_t));

    mem_info.info_type = DRV_FTM_MEM_INFO_MEM_TYPE_DETAIL;
    mem_info.mem_id    = mem_id;
    ret = drv_ftm_get_mem_info(lchip, &mem_info);
    *p_type = mem_info.mem_type;
    *p_order = mem_info.mem_sub_id;
    return  ret;
}

/****************************************************************************************************
||tbl-name                || D2-tbl num   || TM-tbl num  || D2-ramsize(tbl-num/ram)|| D2-ramsize    ||
|| DynamicKeyShareRam12W  || 128k         || 128k        || 8k                     || 8K            ||
|| DynamicAdShareRam12W   || 64k          || 64k         || 8K                     || 8K            ||
|| DynamicEditShareRam12W || 32k          || 64k         || 4K                     || 8K            ||
|| LpmTcamAdMem           || 12k          || 24k         || 2k(if lpm-ad ram is 6) || 4k            ||
|| FlowTcamAdMem          || 16k          || 19k         || 1k                     || 1k            ||
*****************************************************************************************************/
int32
drv_sdb_get_dyn_unite_tbl_info(uint8 lchip ,drv_ser_db_err_mem_info_t err_mem_info, uint32* p_rw_tbl, uint32* p_rw_idx, uint8* p_loop_tm)
{
   uint8  loop_time = 0;
   uint32 rewrite_tbl = 0;
   uint32 rewrite_idx = 0;
   uint16 lpm_bk_start_idx  = 0;
   uint8  err_mem_type   = err_mem_info.err_mem_type;
   uint8  err_mem_order  = err_mem_info.err_mem_order;
   uint32 err_mem_offset = err_mem_info.err_mem_offset;
   uint32 err_entry_size = err_mem_info.err_entry_size;
   uint8  is_mpls = 0;

   loop_time = 1;
   switch (err_mem_type)
   {
       case  DRV_FTM_MEM_DYNAMIC_KEY:
           rewrite_tbl = DynamicKeyShareRam12W_t;
           rewrite_idx = err_mem_order*8*1024 + err_mem_offset/err_entry_size;
           break;
       case  DRV_FTM_MEM_DYNAMIC_AD:
           rewrite_tbl = DynamicAdShareRam12W_t;
           rewrite_idx = err_mem_order*8*1024 + err_mem_offset/err_entry_size;
           break;
       case  DRV_FTM_MEM_DYNAMIC_EDIT:
           rewrite_tbl = DynamicEditShareRam12W_t;
           if (DRV_IS_DUET2(lchip))
           {
               rewrite_idx = err_mem_order*4*1024 + err_mem_offset/err_entry_size;
           }
           else
           {
               rewrite_idx = err_mem_order*8*1024 + err_mem_offset/err_entry_size;
           }
           break;
       case  DRV_FTM_MEM_TCAM_FLOW_AD:
           rewrite_tbl = FlowTcamAdMem_t;
           rewrite_idx = err_mem_order*1*1024 + err_mem_offset/err_entry_size;
           break;
       case  DRV_FTM_MEM_TCAM_LPM_AD:/*RTL Special proc*/
           rewrite_tbl = LpmTcamAdMem_t;
           if (err_mem_order < DRV_SDB_LPM_KEY_BLOCK_NUM*2)
           {
               lpm_bk_start_idx = (err_mem_order % DRV_SDB_LPM_KEY_BLOCK_NUM )*512;
           }
           else
           {
               lpm_bk_start_idx = (err_mem_order % (DRV_SDB_LPM_KEY_BLOCK_NUM*2))*1024;
           }
           if (DRV_IS_DUET2(lchip))
           {
               rewrite_idx = (err_mem_order/DRV_SDB_LPM_KEY_BLOCK_NUM)*4*1024 + lpm_bk_start_idx + err_mem_offset/err_entry_size;
           }
           else
           {
               rewrite_idx = (err_mem_order/DRV_SDB_LPM_KEY_BLOCK_NUM)*4*1024 + lpm_bk_start_idx + (err_mem_offset/err_entry_size)/2;
               rewrite_idx = (rewrite_idx*2) + (err_mem_offset/err_entry_size)%2;
           }
           break;
       case DRV_FTM_MEM_MIXED_KEY:/*TM*/
           drv_usw_ftm_get_mplshash_mode(lchip, &is_mpls);
           if (is_mpls)
           {
               rewrite_tbl = MplsHashKey2w_t;
               loop_time   = DRV_SDB_MPLS_HS_KEY_ECC_SIZE/TABLE_ENTRY_SIZE(lchip, rewrite_tbl);
               rewrite_idx = err_mem_order*8*1024 + (err_mem_offset/err_entry_size)*loop_time;
           }
           else/*xgpon*/
           {
               rewrite_tbl = MplsHashGemPortKey2w_t;
               loop_time   = DRV_SDB_MPLS_HS_KEY_ECC_SIZE/TABLE_ENTRY_SIZE(lchip, rewrite_tbl);
               rewrite_idx = err_mem_order*6*1024 + (err_mem_offset/err_entry_size)*loop_time;
           }
           break;
       case  DRV_FTM_MEM_MIXED_AD:/*TM*/
           drv_usw_ftm_get_mplshash_mode(lchip, &is_mpls);
           if (is_mpls)
           {
               rewrite_tbl = MplsHashAd6w_t;
               rewrite_idx = err_mem_offset/err_entry_size;
           }
           else/*xgpon*/
           {
               rewrite_tbl = MplsHashAd2w_t;
               loop_time   = TABLE_ENTRY_SIZE(lchip, MplsHashAd6w_t)/TABLE_ENTRY_SIZE(lchip, MplsHashAd2w_t);
               rewrite_idx = (err_mem_offset/err_entry_size)*loop_time;
           }
           break;
       case DRV_FTM_MEM_SHARE_MEM:/*TM*/
           if (err_mem_order < 4)
           {
               rewrite_tbl = ShareBufferDsMacKey_t;/*sharebuffer0-3*/
               loop_time   = DRV_SDB_SHARE_BUFFER_ECC_SIZE/TABLE_ENTRY_SIZE(lchip, rewrite_tbl);
               rewrite_idx = err_mem_order*64*1024 + (err_mem_offset/err_entry_size)*loop_time;
           }
           else
           {
               rewrite_tbl = ShareBufferRam3W_t;/*sharebuffer4-6*/
               loop_time   = DRV_SDB_SHARE_BUFFER_ECC_SIZE/TABLE_ENTRY_SIZE(lchip, rewrite_tbl);
               rewrite_idx = (err_mem_order-4)*64*1024 + (err_mem_offset/err_entry_size)*loop_time;
           }



           break;
       default:
           return DRV_E_INVALID_PARAMETER;
           break;
   }

   *p_loop_tm = loop_time;
   *p_rw_tbl  = rewrite_tbl;
   *p_rw_idx  = rewrite_idx;

    return DRV_E_NONE;
}

int32
drv_sdb_rewrite_acc_tbl(uint8 lchip, uint16 tbl_id, uint16 tbl_idx,uint8* p_data)
{
    uint8     cam_type  = 0;
    uint8     cam_num   = 0;
    int32     ret       = 0;
    drv_acc_in_t  in;
    drv_acc_out_t out;

    sal_memset(&in, 0, sizeof(in));
    sal_memset(&out, 0, sizeof(out));
    in.type = DRV_ACC_TYPE_ADD;
    in.op_type = DRV_ACC_OP_BY_INDEX;
    in.tbl_id = tbl_id;
    in.index  = tbl_idx;
    in.data   = (void*)p_data;
    drv_acc_get_hash_module( lchip, tbl_id, &in.module);
    ret += drv_usw_ftm_get_cam_by_tbl_id(lchip, in.tbl_id, &cam_type, &cam_num);
    if (!cam_num)
    {
        DRV_DBG_INFO("DRV_mem_db:can not get this tbl cam_num.\n");
    }
    in.index += cam_num;
    ret += drv_acc_api(lchip, (void*)&in, (void*)&out);

    return ret;
}

int32 drv_sdb_get_tcam_local_entry_size(uint8 lchip, uint8 mem_id, uint32*p_entry_size)
{
    drv_ftm_mem_info_t mem_info;

    sal_memset(&mem_info, 0 ,sizeof(drv_ftm_mem_info_t));
    mem_info.mem_id = mem_id;
    mem_info.info_type = DRV_FTM_MEM_INFO_MEM_TYPE_DETAIL;
    drv_ftm_get_mem_info(lchip, &mem_info);

    switch (mem_info.mem_type)
    {
        case DRV_FTM_MEM_TCAM_FLOW_KEY:
            *p_entry_size = DRV_BYTES_PER_ENTRY;
            break;
        case DRV_FTM_MEM_TCAM_LPM_KEY:
            *p_entry_size = DRV_LPM_KEY_BYTES_PER_ENTRY;
            break;
        case DRV_FTM_MEM_TCAM_CID_KEY:
            *p_entry_size = 1*4;
            break;
        case DRV_FTM_MEM_TCAM_QUEUE_KEY:
            *p_entry_size = (DRV_IS_DUET2(lchip) ? (2*4):(3*4));
            break;
        default:
            *p_entry_size = 0;
            return  DRV_E_INVALID_PARAMETER;
            break;
    }

    return  DRV_E_NONE;
}

uint8
_drv_sdb_get_ram_type(uint8 lchip, uint8 ram_id, uint8 is_detail)
{
    drv_ftm_mem_info_t mem_info;
    int32 ret = 0;

    sal_memset(&mem_info, 0, sizeof(drv_ftm_mem_info_t));
    mem_info.info_type = is_detail ? DRV_FTM_MEM_INFO_MEM_TYPE_DETAIL : DRV_FTM_MEM_INFO_MEM_TYPE;
    mem_info.mem_id = ram_id;
    ret = drv_ftm_get_mem_info(lchip, &mem_info);

    if (ret == 0)
    {
        return mem_info.mem_type;
    }
    else
    {
        return 0xff;
    }
}

STATIC INLINE uint8
_drv_sdb_get_tbl_type(uint8 lchip, tbls_id_t tb_id)
{
    int32 ret = 0;
    drv_ftm_tbl_detail_t tbl_info;

    sal_memset(&tbl_info, 0, sizeof(drv_ftm_tbl_detail_t));
    tbl_info.type = DRV_FTM_TBL_TYPE;
    tbl_info.tbl_id = tb_id;
    ret = drv_ftm_get_tbl_detail(lchip, &tbl_info);

    if (ret == 0)
    {
        return tbl_info.tbl_type;
    }
    else
    {
        return 0xff;
    }
}

STATIC INLINE uint32
_drv_sdb_get_entry_offset(uint8 lchip, uint32 sram_type, uint32 entry_id, uint32 entry_size, drv_sdb_t* p_sdb)
{
    uint32 local_size = 0;
    uint32 entry_offset = 0;
    uint8 mem_id = ((sram_type>>24) & 0xFF);

    entry_offset = entry_id*entry_size;
    sram_type = sram_type & 0xFFFFFF;
    
    drv_usw_get_memory_size(lchip, mem_id, &local_size);
    local_size = local_size/2;
    
    if ((p_drv_master[lchip]->dev_type == DRV_TSINGMA_MX) && DRV_FTM_SRAM_TBL_LPM_LKP_KEY0 == sram_type && entry_offset >= local_size)
    {
        return ((DRV_SDB_ADDR_BASE(DsNeoLpmMemorySnakeP2_t)-DRV_SDB_ADDR_BASE(DsNeoLpmMemorySnakeP1_t))+
                entry_offset - local_size);
    }
    else if (p_drv_master[lchip]->dev_type >= DRV_ARCTIC && DRV_FTM_SRAM_TBL_LPM_LKP_KEY0 == sram_type) 
    {
        if ((2 == mem_id || 3 == mem_id) && (entry_offset >= local_size))/* L0 */
        {
            return ((DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32SnakeExt1_t)-DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32SnakeExt0_t))+
                    entry_offset - local_size);
        }
        else if (entry_offset >= local_size) /* L1 */
        {
            return ((DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t)-DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake0_t))+
                    entry_offset - local_size);
        }
        else
        {
            return (entry_offset);
        }
    }
    else
    {
        return (entry_offset);
    }
}

/*mode 0:static tbl size;1 dynamic size;2 total*/
uint32
drv_sdb_calc_tbl_size(uint8 lchip, uint8 mode)
{
    uint8  ram_type = 0;
    uint32 loop = 0;
    uint32 total_byte[3] = {0};
    uint32 mem_size = 0;
    uint8 pp_base = drv_vchip_get_pp_base(lchip);
    uint32 sram_tbl_a[200] = {0};
    uint8  share_tbl_num  = 0;
    uint8  per_tbl_entry_num = 0;
    uint32 sram_type = 0;
    uint8 coefficient = 0;
#if (SDB_TIMESTAMP == SDB_MODE)
    uint16 tbl_type = 0;
    uint32 is_couple = 0;
#endif
    if(mode != 1)
    {
        for (loop = 0; loop < MaxTblId_t; loop++ )
        {
            if (_drv_sdb_get_tbl_type(lchip, loop) != DRV_FTM_TABLE_STATIC && TABLE_EXT_INFO_TYPE(lchip, loop) != EXT_INFO_TYPE_STATIC_TCAM_KEY)
            {
                continue;
            }
            if (!DRV_SDB_MODE_VALID(loop))
            {
                continue;
            }
            if ((lchip != pp_base) && (lchip != pp_base + p_drv_master[lchip]->core_pp_num) && TABLE_ENTRY_TYPE(lchip, loop) == DRV_FEATURE_MODE_PER_CORE)
            {
                continue;
            }
            else if (lchip != pp_base && DRV_TBL_FEA_MOD(loop) == DRV_FEATURE_MODE_PER_CORE && TABLE_ENTRY_TYPE(lchip, loop) != DRV_FEATURE_MODE_PER_CORE)
            {
                continue;
            }
            total_byte[0]  += (((TABLE_MAX_INDEX(lchip, loop)) * (DRV_TBL_TCAM_MEM(loop) ? TABLE_ENTRY_OFFSET(lchip, loop) : TABLE_ENTRY_SIZE(lchip, loop)))
               << (DRV_FEATURE_MODE_PER_DP == DRV_TBL_FEA_MOD(loop) || DRV_FEATURE_MODE_PEER_DP == DRV_TBL_FEA_MOD(loop)));
#if (SDB_TIMESTAMP == SDB_MODE)
            total_byte[0]  += sizeof(drv_sdb_ts_hdr_t) + (((TABLE_MAX_INDEX(lchip, loop)) * DRV_SDB_TS_SIZE) <<
               (DRV_FEATURE_MODE_PER_DP == DRV_TBL_FEA_MOD(loop) || DRV_FEATURE_MODE_PEER_DP == DRV_TBL_FEA_MOD(loop)));
#endif
        }
    }

    if(mode != 0)
    {
        for (loop = 0; loop < DRV_FTM_MAX_ID; loop++)
        {
            mem_size = 0;
            drv_usw_get_memory_size(lchip, loop, &mem_size);
            ram_type = _drv_sdb_get_ram_type(lchip, loop, 0);
            if (ram_type == DRV_FTM_MEM_TCAM)
            {
                continue;
            }
            if (mem_size == 0 || FALSE == drv_usw_ftm_sram_use_sdb(lchip, loop))
            {
                continue;
            }
            if (loop < DRV_FTM_EDRAM_MAX)
            {
                sram_type = drv_usw_ftm_memid_2_table(lchip, loop);
                drv_usw_ftm_get_sram_tbl_id(lchip, sram_type, sram_tbl_a, &share_tbl_num, &per_tbl_entry_num);
                coefficient = ((TABLE_ENTRY_TYPE(lchip, sram_tbl_a[0]) == DRV_FEATURE_MODE_PER_CORE)? 1:\
                           ((DRV_TBL_FEA_MOD(sram_tbl_a[0]) == DRV_FEATURE_MODE_PER_CORE)? 0:3));
            }
            else if (loop < DRV_FTM_TCAM_AD4)
            {
                coefficient = ((DRV_TBL_FEA_MOD(DsTunnelId0Tcam_t) == DRV_FEATURE_MODE_PER_CORE)? 0:3);
            }
            else if (loop < DRV_FTM_TCAM_AD40)
            {
                coefficient = ((DRV_TBL_FEA_MOD(DsAcl0Ingress_t) == DRV_FEATURE_MODE_PER_CORE)? 0:3);
            }
            else if (loop < DRV_FTM_TCAM_ADM)
            {
                coefficient = ((DRV_TBL_FEA_MOD(DsEgressScl0TcamAd_t) == DRV_FEATURE_MODE_PER_CORE)? 0:3);
            }
            else
            {
                coefficient = ((DRV_TBL_FEA_MOD(DsLpmTcamIpv6DoubleKey0Ad_t) == DRV_FEATURE_MODE_PER_CORE)? 0:3);
            }
            if ((lchip != pp_base) && (p_drv_master[lchip]->dev_type >= DRV_ARCTIC))
            {
                if ((lchip != (pp_base + p_drv_master[lchip]->core_pp_num) && 1 == coefficient))
                {
                    continue;  /* core tbl only store in core base */
                } 
                else if (!coefficient)
                {
                    continue;  /* pp tbl global access only save in pp base  */
                }
            }
            total_byte[1] += mem_size;
#if (SDB_TIMESTAMP == SDB_MODE)
            tbl_type = drv_usw_ftm_memid_2_table(lchip, loop);
            drv_usw_get_dynamic_ram_couple_mode(lchip, tbl_type, &is_couple);

            total_byte[1] += sizeof(drv_sdb_ts_hdr_t) + ((DRV_MEM_ENTRY_NUM(lchip, loop)<<is_couple) * DRV_SDB_TS_SIZE);
#endif
            /*printf("calc tablename :%d, size:%u\n", loop,mem_size);*/
        }
    }
    total_byte[2] = total_byte[0] + total_byte[1];
    return total_byte[mode];
}

STATIC int32
_drv_sdb_reset_register(uint8 lchip, uint8 is_recover)
{
    uint32 cmd      = 0;
    uint32 index    = 0;
    uint32 value    = 0;

    for (index = 0; (index < (sizeof(drv_sdb_reset_hw_register)/sizeof(drv_sdb_reset_hw_register_t))); index ++)
    {
        if(drv_sdb_reset_hw_register[index].type == 1)
        {
            if (!is_recover)/*store*/
            {
                cmd = DRV_IOR(drv_sdb_reset_hw_register[index].tbl_id, drv_sdb_reset_hw_register[index].fld_id);
                DRV_IF_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd,  &value));
                drv_sdb_reset_hw_register[index].old_value = value;
            }
            else/*recover*/
            {
                cmd = DRV_IOW(drv_sdb_reset_hw_register[index].tbl_id, drv_sdb_reset_hw_register[index].fld_id);
                value = drv_sdb_reset_hw_register[index].old_value;
                DRV_IF_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd,  &value));
                continue;
            }
        }
        value = drv_sdb_reset_hw_register[index].value;
        cmd = DRV_IOW(drv_sdb_reset_hw_register[index].tbl_id, drv_sdb_reset_hw_register[index].fld_id);
        DRV_IF_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
     }
     return DRV_E_NONE;
}

STATIC int32
_drv_sdb_reset_static(uint8 lchip, uint8 enable)
{
    uint8* p_bucket_data = NULL;
    uint32*   temp_dma_memory = NULL;
    uint32 tbl_id = 0;
    uint32 tbl_index = 0;
    uint32 start_data_addr = 0;
    uint32   copy_entry_num = 0;
    uint32   tmp_entry_index = 0;
    uint32    entry_offset = 0;
    uint32 loop_cnt;
    uint32 loop;
    uint32 once_entry_num;
    drv_dma_tbl_rw_t dma_cfg;
    uint32  entry_size;
    uint32  entry_num;
    uint8  mem_block_num;
    uint8  loop1;
    uint8  tcam_block_shift = 0;
    uint8 tcam_block_id = 0;
    uint8 tcam_mem_id_base = 0;
    uint8 tcam_step;
    uint8 dp_tbl = 0;
    uint8 oper_bmp = 0, base_lchip = drv_vchip_get_pp_base(lchip);
    drv_sdb_t* p_sdb = (drv_sdb_t*)(g_sdb_master[lchip]);

    sal_memset(&dma_cfg, 0, sizeof(drv_dma_tbl_rw_t));
    if (enable == 0)
    {
        return DRV_E_NONE;
    }

    for (tbl_id = 0 ; tbl_id < MaxTblId_t; tbl_id ++)
    {
        DRV_SDB_IF_CONTINUE(!DRV_SDB_MODE_VALID(tbl_id));
        DRV_SDB_IF_CONTINUE(_drv_sdb_get_tbl_type(lchip, tbl_id) != DRV_FTM_TABLE_STATIC);
        DRV_SDB_IF_CONTINUE(NULL == p_sdb->static_tbl[tbl_id]);

        /*DRV_DBG_INFO("Reset table id [%u], max index [%u]\n", tbl_id, TABLE_MAX_INDEX(lchip, tbl_id));*/
        /* per PP -> core and per core */
        if (DRV_TBL_FEA_MOD(tbl_id) == DRV_FEATURE_MODE_PER_CORE && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_CORE)
        {
            oper_bmp = 0xFC&(p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, tbl_id)]);
            if (lchip != base_lchip)
            {
                continue;
            }
        }
        else if (TABLE_ENTRY_TYPE(lchip, tbl_id) == DRV_FEATURE_MODE_PER_CORE)
        {
            oper_bmp = p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1];
            if ((lchip != base_lchip) && (lchip != base_lchip + p_drv_master[lchip]->core_pp_num))
            {
                continue;
            }
        }
        else /*other include DP 0*/
        {
            oper_bmp = (p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1] | p_drv_master[lchip]->pp_bmp[g_drv_chip[lchip].pp_id] | 1)&
                       (p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, tbl_id)]);
        }

        /*1. Since the address of multiple DP may not be consecutive,judge use dma or not*/
        if((TABLE_ENTRY_TYPE(lchip, tbl_id) != SLICE_Cascade) && \
            (TABLE_ADDR_NUM(lchip, tbl_id) <= 1) && \
            (TABLE_MAX_INDEX(lchip, tbl_id) >= 8) && \
            (p_sdb->dma_write_cb) && ((p_sdb->dma_wait_done_cb)))
        {
            entry_size = TABLE_ENTRY_SIZE(lchip, tbl_id);
            entry_offset = TABLE_ENTRY_OFFSET(lchip, tbl_id);
            entry_num = TABLE_MAX_INDEX(lchip, tbl_id);
            dp_tbl = 0;
            
            loop1 = 0;
            mem_block_num = 1;
            tcam_block_shift = 0;
            tcam_step = 0;
            if (tbl_id == FlowTcamTcamMem_t)
            {
                tcam_block_shift = p_drv_master[lchip]->drv_io_tcam_db[DRV_IO_TCAM_TYPE_FLOW].blk_shift;
                mem_block_num = TABLE_MAX_INDEX(lchip, tbl_id)>>tcam_block_shift;
                tcam_mem_id_base = DRV_FTM_TCAM_KEY0;
                tcam_step = 1;
            }
            else if (tbl_id == LpmTcamTcamMem_t)
            {
                tcam_block_shift = p_drv_master[lchip]->drv_io_tcam_db[DRV_IO_TCAM_TYPE_LPM].blk_shift;
                mem_block_num = TABLE_MAX_INDEX(lchip, tbl_id)>>tcam_block_shift;
                tcam_mem_id_base = DRV_FTM_LPM_TCAM_KEY0;
                tcam_step = (p_drv_master[lchip]->dev_type >= DRV_TSINGMA_MX)? 2 :4;
            }
            else if ((p_drv_master[lchip]->dev_type >= DRV_ARCTIC) && (TABLE_ENTRY_TYPE(lchip, tbl_id) == DRV_FEATURE_MODE_PER_DP || TABLE_ENTRY_TYPE(lchip, tbl_id) == DRV_FEATURE_MODE_PEER_DP))
            {
                /*for DP & PEER DP table, need read dp0 & dp1*/
                mem_block_num = 2;
                dp_tbl = 1;
            }

            /*2. Flow tcam and lpm tcam address is not consecutive, split into multiple dma operation*/
            do
            {
                tbl_index = 0;
                once_entry_num = TABLE_MAX_INDEX(lchip, tbl_id);
                if(tcam_step)
                {
                    tbl_index = loop1*(1<<tcam_block_shift);
                    tcam_block_id = tbl_index >> tcam_block_shift;
                    once_entry_num = DRV_MEM_ENTRY_NUM(lchip, tcam_mem_id_base+tcam_block_id*tcam_step)*tcam_step;
                    entry_num = once_entry_num;
                }

                /*3. Judge whether a DMA operation can write one consecutive memory*/
                once_entry_num = (DRV_SDB_MAX_DMA_SIZE(lchip)/entry_offset > once_entry_num) ? once_entry_num : (DRV_SDB_MAX_DMA_SIZE(lchip)/entry_offset);
                loop_cnt = (entry_num+once_entry_num-1)/once_entry_num;

                loop = 0;
                dma_cfg.entry_len = entry_size;
                dma_cfg.user_dma_mode = 1;
                dma_cfg.entry_offset = entry_offset;
                oper_bmp = ((oper_bmp & (~(3))) | 1)&(p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, tbl_id)]);
                if (dp_tbl && loop1 == 1)
                {
                    /*oper for dp1*/
                    oper_bmp = (oper_bmp & (~(3))) | 2;
                }
                dma_cfg.op_bmp = oper_bmp;
                do
                {
                    /*3.1 wait current dma bucket done, 0xFFFF means not used*/
                    if(p_sdb->desc_index_map[p_sdb->dma_mem_idx] != DRV_SDB_DMA_INVALID_DESC_IDX)
                    {
                        DRV_IF_ERROR_RETURN(p_sdb->dma_wait_done_cb(lchip, 0, p_sdb->desc_index_map[p_sdb->dma_mem_idx]));
                    }
                    
                    temp_dma_memory = p_sdb->dma_mem_bucket[p_sdb->dma_mem_idx];
                    dma_cfg.buffer = temp_dma_memory;
                    copy_entry_num = (loop == loop_cnt-1) ? (entry_num-loop*once_entry_num) : once_entry_num;

                    drv_usw_table_get_hw_addr(lchip, tbl_id, tbl_index, &start_data_addr,0);
                    dma_cfg.tbl_addr = start_data_addr;
                    dma_cfg.entry_num = copy_entry_num;
                    /*DRV_DBG_INFO("Use DMA, entry_size %u, entry offset %u, tbl index %u, hw addr 0x%x\n", entry_size,entry_offset, tbl_index, start_data_addr);*/
                    /*3.2 copy from sdb to dma memory one by one*/
                    tmp_entry_index = 0;
                    do
                    {
                        p_bucket_data = p_sdb->static_tbl[tbl_id] + tbl_index * (DRV_TBL_TCAM_MEM(tbl_id)? TABLE_ENTRY_OFFSET(lchip, tbl_id): TABLE_ENTRY_SIZE(lchip, tbl_id));
                        if (dp_tbl && loop1 == 1)
                        {
                            /* DP1 */
                            p_bucket_data = p_sdb->static_tbl[tbl_id] + (tbl_index + TABLE_MAX_INDEX(lchip, tbl_id))*TABLE_ENTRY_SIZE(lchip, tbl_id);
                        }
                        sal_memcpy((uint8*)temp_dma_memory+tmp_entry_index*entry_offset, p_bucket_data, entry_size);
                        ++tbl_index;
                    }while(++tmp_entry_index < copy_entry_num);

                    DRV_IF_ERROR_RETURN(p_sdb->dma_write_cb(lchip, &dma_cfg));

                    /*3.3 record the descriptor index returned by dma*/
                    p_sdb->desc_index_map[p_sdb->dma_mem_idx] = dma_cfg.desc_index;
                    p_sdb->dma_mem_idx = ((p_sdb->dma_mem_idx + 1) == DRV_SDB_DMA_BUCKET_NUM) ? 0 : (p_sdb->dma_mem_idx+1);
                }while(++loop < loop_cnt);
            }while(++loop1 < mem_block_num);
        }
        else
        {
            uint32 need_continue;
            uint32 step = 0;
            uint32 tcam_mem_id = 0;
            uint32 tcam_local_index = 0;
            
            need_continue = 0;
            step = 1;
            if (tbl_id == FlowTcamTcamMem_t)
            {
                tcam_block_shift = p_drv_master[lchip]->drv_io_tcam_db[DRV_IO_TCAM_TYPE_FLOW].blk_shift;
                tcam_mem_id = DRV_FTM_TCAM_KEY0;
                need_continue = 1;
            }
            else if (tbl_id == LpmTcamTcamMem_t)
            {
                tcam_block_shift = p_drv_master[lchip]->drv_io_tcam_db[DRV_IO_TCAM_TYPE_LPM].blk_shift;
                tcam_mem_id = DRV_FTM_LPM_TCAM_KEY0;
                step = (p_drv_master[lchip]->dev_type >= DRV_TSINGMA_MX)? 2: 4;
                need_continue = 1;
            }
            
            for (tbl_index = 0; tbl_index < TABLE_MAX_INDEX(lchip, tbl_id); tbl_index++)
            {
                
                if (need_continue)
                {
                    tcam_block_id = tbl_index >> tcam_block_shift;
                    tcam_local_index = tbl_index & ((1<<tcam_block_shift)-1);
                    DRV_SDB_IF_CONTINUE(tcam_local_index >= DRV_MEM_ENTRY_NUM(lchip, tcam_mem_id+tcam_block_id*step)*step);
                }
                oper_bmp = ((oper_bmp & (~(3))) | 1)&(p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, tbl_id)]);
                p_bucket_data = p_sdb->static_tbl[tbl_id] + tbl_index * (DRV_TBL_TCAM_MEM(tbl_id)? TABLE_ENTRY_OFFSET(lchip, tbl_id): TABLE_ENTRY_SIZE(lchip, tbl_id));
                drv_usw_table_get_hw_addr(lchip, tbl_id, tbl_index, &start_data_addr,0);
                start_data_addr += !(TABLE_OP_TYPE(lchip, tbl_id)&Op_DisBurst) && p_drv_master[lchip]->burst_en;
                drv_usw_chip_write_sram_entry(lchip, ((uint64)oper_bmp<<32)|start_data_addr, (uint32*)p_bucket_data, TABLE_ENTRY_SIZE(lchip, tbl_id));
                if ((p_drv_master[lchip]->dev_type < DRV_ARCTIC) || 
                    (TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_DP && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PEER_DP))
                {
                    continue;
                }

                /* DP 1 */
                oper_bmp = (oper_bmp & (~(3))) | 2;
                p_bucket_data = p_sdb->static_tbl[tbl_id] + (tbl_index + TABLE_MAX_INDEX(lchip, tbl_id))*TABLE_ENTRY_SIZE(lchip, tbl_id);
                drv_usw_chip_write_sram_entry(lchip, ((uint64)oper_bmp<<32)|start_data_addr, (uint32*)p_bucket_data, TABLE_ENTRY_SIZE(lchip, tbl_id));
            }
        }
    }

    return DRV_E_NONE;
}
STATIC int32
_drv_sdb_reset_per_ram_by_io(uint8 lchip, uint8 mem_id, uint8 oper_bmp)
{
    uint32   entry_id = 0;
    uint32   entry_num = 0;
    uint32   mem_size = 0, entry_size = 0;
    uint32*  hw_addr_array = &DRV_MEM_INFO(lchip, mem_id).addr_3w;
    uint8*   sw_addr = 0;
    uint32   entry_offset = 0;
    uint8    burst_write = 0;
    uint8    sram_type = 0;
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    uint8*   p_sw_buffer = NULL;
    uint8    dp_id = (oper_bmp>>1)&0x1;

    entry_size = DRV_MEM_ENTRY_SIZE(lchip, mem_id);
    if (NULL == p_sdb || NULL == p_sdb->dynamic_tbl[mem_id] || entry_size == 0)
    {
        return DRV_E_NONE;
    }
    DRV_IF_ERROR_RETURN(drv_usw_ftm_get_sram_type(lchip, mem_id, &sram_type));
    if (DRV_FROM_TMM(lchip) && DRV_FTM_SRAM_TBL_MPLS_HASH_KEY == sram_type)
    {
        hw_addr_array = &DRV_MEM_INFO(lchip, mem_id).addr_6w;
    }
    DRV_SDB_ENTRY_SIZE_ALINE(entry_size, entry_offset);
    drv_usw_get_memory_size(lchip, mem_id, &mem_size);
    entry_num = mem_size / entry_size;

    /*DRV_DBG_INFO("Mem[%u] reset...\n", mem_id);*/
    sw_addr = p_sdb->dynamic_tbl[mem_id] + (dp_id? mem_size<<2: 0);
    do
    {
        p_sw_buffer = sw_addr + _drv_sdb_get_entry_offset(lchip, ((mem_id<<24) | sram_type), entry_id, entry_size, p_sdb);
        drv_usw_chip_write_sram_entry(lchip, ((uint64)oper_bmp<<32)|(hw_addr_array[DRV_MEM_ADDR_SEL(lchip, mem_id)]+entry_id*entry_offset+burst_write), (uint32*)p_sw_buffer, entry_size);
    }while(++entry_id < entry_num);
    return DRV_E_NONE;
}

STATIC int32
_drv_sdb_reset_per_ram_by_dma(uint8 lchip, uint8 mem_id, uint8 oper_bmp)
{
    uint32*  hw_addr_array = &DRV_MEM_INFO(lchip, mem_id).addr_3w;
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    drv_dma_tbl_rw_t dma_cfg;
    uint32*   temp_dma_memory = NULL;
    uint8*   sw_addr = 0;
    uint8*   p_sw_buffer = NULL;
    uint32   entry_offset;
    uint32   loop_cnt;
    uint32   loop;
    uint32   once_entry_num;
    int32    ret = 0;
    uint32   entry_id = 0;
    uint32   entry_num = 0;
    uint32   mem_size = 0, entry_size = 0;
    uint16   copy_entry_num = 0;
    uint16   tmp_entry_index = 0;
    uint8    sram_type = 0;
    uint8    dp_id = (oper_bmp>>1)&0x1;

    sal_memset(&dma_cfg, 0, sizeof(drv_dma_tbl_rw_t));
    entry_size = DRV_MEM_ENTRY_SIZE(lchip, mem_id);
    if (NULL == p_sdb || NULL == p_sdb->dynamic_tbl[mem_id] || entry_size == 0)
    {
        return DRV_E_NONE;
    }

    drv_usw_get_memory_size(lchip, mem_id, &mem_size);
    entry_num = mem_size / entry_size;
    DRV_SDB_ENTRY_SIZE_ALINE(entry_size, entry_offset);

    /*1. Judge whether a DMA operation can write one consecutive memory*/
    loop = 0;
    once_entry_num = DRV_SDB_MAX_DMA_SIZE(lchip)/entry_offset;
    loop_cnt = (entry_num+once_entry_num-1)/once_entry_num;

    DRV_IF_ERROR_RETURN(drv_usw_ftm_get_sram_type(lchip, mem_id, &sram_type));
    if (DRV_FROM_TMM(lchip) && DRV_FTM_SRAM_TBL_MPLS_HASH_KEY == sram_type)
    {
        hw_addr_array = &DRV_MEM_INFO(lchip, mem_id).addr_6w;
    }
    
    do
    {
        /*2. wait current dma bucket done*/
        if(p_sdb->desc_index_map[p_sdb->dma_mem_idx] != DRV_SDB_DMA_INVALID_DESC_IDX)
        {
            DRV_IF_ERROR_RETURN(p_sdb->dma_wait_done_cb(lchip, 0, p_sdb->desc_index_map[p_sdb->dma_mem_idx]));
        }
        
        temp_dma_memory = p_sdb->dma_mem_bucket[p_sdb->dma_mem_idx];
        dma_cfg.buffer = temp_dma_memory;
        copy_entry_num = (loop == loop_cnt-1) ? (entry_num-loop*once_entry_num) : once_entry_num;
        
        dma_cfg.tbl_addr = (hw_addr_array[DRV_MEM_ADDR_SEL(lchip, mem_id)]+loop*DRV_SDB_MAX_DMA_SIZE(lchip));
        dma_cfg.entry_num = copy_entry_num;
        dma_cfg.entry_len = entry_size;
        dma_cfg.user_dma_mode = 1;
        dma_cfg.entry_offset = entry_offset;
        dma_cfg.op_bmp = oper_bmp;

        /*3. copy from sdb to dma memory*/
        sw_addr = p_sdb->dynamic_tbl[mem_id] + (dp_id? mem_size<<2: 0);
        tmp_entry_index = 0;
        do
        {
            p_sw_buffer = sw_addr + _drv_sdb_get_entry_offset(lchip, ((mem_id<<24) | sram_type), entry_id, entry_size, p_sdb);
            sal_memcpy((uint8*)temp_dma_memory+tmp_entry_index*entry_offset, p_sw_buffer, entry_size);
            ++entry_id;
        }while(++tmp_entry_index < copy_entry_num);

        /*DRV_SDB_DUMP("dma_cfg.tbl_addr_hex:0x%10x dma_cfg.buffer:0x%10x,dma_cfg.entry_num:%10u,dma_cfg.entry_len:%10u \n", dma_cfg.tbl_addr,dma_cfg.buffer, dma_cfg.entry_num,dma_cfg.entry_len);*/
        DRV_IF_ERROR_GOTO(p_sdb->dma_write_cb(lchip, &dma_cfg), ret, error_rollback);

        /*4. record the descriptor index returned by dma*/
        p_sdb->desc_index_map[p_sdb->dma_mem_idx] = dma_cfg.desc_index;
        p_sdb->dma_mem_idx = ((p_sdb->dma_mem_idx + 1) == DRV_SDB_DMA_BUCKET_NUM) ? 0 : (p_sdb->dma_mem_idx+1);
        
    }while(++loop < loop_cnt);

error_rollback:
    return ret;
}


STATIC int32
_drv_sdb_reset_dynamic(uint8 lchip, uint8 enable)
{
    uint8 mem_id = 0;
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    uint8 pp_base = drv_vchip_get_pp_base(lchip);
    uint32 sram_tbl_a[200] = {0};
    uint8  share_tbl_num  = 0;
    uint8  per_tbl_entry_num = 0;
    uint32 sram_type = 0;
    uint8 tbl_type = 0; /* 0: PP->core 1: core 2: other */
    uint8 oper_bmp = 0;

    if (enable == 0)
    {
        return DRV_E_NONE;
    }

    if (DRV_MCHIP_FTM_API(lchip)->ftm_reset_dynamic_table)
    {
        DRV_IF_ERROR_RETURN(DRV_MCHIP_FTM_API(lchip)->ftm_reset_dynamic_table(lchip));
    }

    for (mem_id = 0 ; mem_id < DRV_FTM_MAX_ID; mem_id++ )
    {
        if (mem_id < DRV_FTM_EDRAM_MAX)
        {
            sram_type = drv_usw_ftm_memid_2_table(lchip, mem_id);
            drv_usw_ftm_get_sram_tbl_id(lchip, sram_type, sram_tbl_a, &share_tbl_num, &per_tbl_entry_num);
            tbl_type = ((TABLE_ENTRY_TYPE(lchip, sram_tbl_a[0]) == DRV_FEATURE_MODE_PER_CORE)? 1:\
                       ((DRV_TBL_FEA_MOD(sram_tbl_a[0]) == DRV_FEATURE_MODE_PER_CORE)? 0:2));
            oper_bmp = 0xFC&(p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, sram_tbl_a[0])]);
        }
        else if (mem_id < DRV_FTM_TCAM_AD4)
        {
            tbl_type = ((DRV_TBL_FEA_MOD(DsTunnelId0Tcam_t) == DRV_FEATURE_MODE_PER_CORE)? 0:2);
            oper_bmp = 0xFC&(p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, DsTunnelId0Tcam_t)]);
        }
        else if (mem_id < DRV_FTM_TCAM_AD40)
        {
            tbl_type = ((DRV_TBL_FEA_MOD(DsAcl0Ingress_t) == DRV_FEATURE_MODE_PER_CORE)? 0:2);
            oper_bmp = 0xFC&(p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, DsAcl0Ingress_t)]);
        }
        else if (mem_id < DRV_FTM_TCAM_ADM)
        {
            tbl_type = ((DRV_TBL_FEA_MOD(DsEgressScl0TcamAd_t) == DRV_FEATURE_MODE_PER_CORE)? 0:2);
            oper_bmp = 0xFC&(p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, DsEgressScl0TcamAd_t)]);
        }
        else
        {
            tbl_type = ((DRV_TBL_FEA_MOD(DsLpmTcamIpv6DoubleKey0Ad_t) == DRV_FEATURE_MODE_PER_CORE)? 0:2);
            oper_bmp = 0xFC&(p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, DsLpmTcamIpv6DoubleKey0Ad_t)]);
        }
        if (!tbl_type)
        {
            if (lchip != pp_base)
            {
                continue;
            }
        }
        else if (1 == tbl_type)
        {
            oper_bmp = p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1];
            if ((lchip != pp_base) && (lchip != pp_base + p_drv_master[lchip]->core_pp_num))
            {
                continue;
            }
        }
        else
        {
            oper_bmp = p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1] | p_drv_master[lchip]->pp_bmp[g_drv_chip[lchip].pp_id];
        }
        /*Since the table address may not be consecutive*/
        if(p_drv_master[lchip]->p_mem_info[mem_id].index_map || \
            (NULL == p_sdb->dma_write_cb) || (NULL == p_sdb->dma_wait_done_cb))
        {
            if (mem_id >= DRV_FTM_SRAM47 && mem_id <= DRV_FTM_SRAM54)
            {
                /* DP 0 */
                oper_bmp = (oper_bmp & (~(3))) | 1;
                DRV_IF_ERROR_RETURN(_drv_sdb_reset_per_ram_by_io(lchip, mem_id, oper_bmp));
                /* DP 1 */
                oper_bmp = (oper_bmp & (~(3))) | 2;
                DRV_IF_ERROR_RETURN(_drv_sdb_reset_per_ram_by_io(lchip, mem_id, oper_bmp));
            }
            else
            {
                DRV_IF_ERROR_RETURN(_drv_sdb_reset_per_ram_by_io(lchip, mem_id, oper_bmp));
            }
        }
        else
        {
            if (mem_id >= DRV_FTM_SRAM47 && mem_id <= DRV_FTM_SRAM54)
            {
                /* DP 0 */
                oper_bmp = (oper_bmp & (~(3))) | 1;
                DRV_IF_ERROR_RETURN(_drv_sdb_reset_per_ram_by_dma(lchip, mem_id, oper_bmp));
                /* DP 1 */
                oper_bmp = (oper_bmp & (~(3))) | 2;
                DRV_IF_ERROR_RETURN(_drv_sdb_reset_per_ram_by_dma(lchip, mem_id, oper_bmp));
            }
            else
            {
                DRV_IF_ERROR_RETURN(_drv_sdb_reset_per_ram_by_dma(lchip, mem_id, oper_bmp));
            }
        }
    }
    return DRV_E_NONE;
}

#ifdef SDK_IN_DEBUG_VER
#define DRV_SDB_BUFFER_DUMP(name, buffer, size)   \
{\
    uint32 _loop_ = 0;\
    if (NULL != pf) {\
        sal_fprintf(pf, name);\
        do{\
            sal_fprintf(pf, "%08x ", ((uint32*)buffer)[_loop_]);\
        }while(++_loop_ < ((size+3)>>2));\
        sal_fprintf(pf, "\n");\
    } else { \
    sal_printf(name);\
    do{\
        sal_printf("%08x ", ((uint32*)buffer)[_loop_]);\
    }while(++_loop_ < ((size+3)>>2));\
    sal_printf("\n");\
    }\
}
#else
#define DRV_SDB_BUFFER_DUMP(name, buffer, size)
#endif

int32
_drv_sdb_check_tcam(uint8 lchip, uint8 mem_id, uint8 oper_bmp, uint8 flag, uint8* cmp_result, sal_file_t pf)
{
    uint8    have_valid_word = 0;
    uint8    word_num = 0;
    uint32   entry_id = 0;
    uint32   entry_num = 0, entry_size = 0;
    uint32   entry_size_per_index = 0;
    uint32   mem_addr     = 0;
    uint32*  p_hw_buffer = NULL;
    uint32*  p_sw_buffer = NULL;
    uint32   index = 0;
    drv_ftm_tcam_info_t tcam_info;

    DRV_SDB_DUMP_FILE(pf, "TCAM checking[lchip:%d][mem_id:%u]...\n", lchip, mem_id);
    drv_usw_ftm_get_tcam_memory_info(lchip, mem_id, &mem_addr, &entry_num, &entry_size, &tcam_info);
    if (!DRV_SDB_MODE_VALID(tcam_info.tcam_mem_id))
    {
        return DRV_E_NONE;
    }
#ifdef EMULATION_ENV
    entry_num = 32;
#endif
    /*
    DRV_SDB_DUMP_FILE(pf, "Mem info: mem_addr:0x%x - entry_num:%u - entry_size:%u - entry_offset:%u - sdb_addr:%p\n",
                 mem_addr, entry_num, entry_size, tcam_info.entry_offset, (uint8*)tcam_info.sw_addr);
    */
    word_num = entry_size>>2;
    have_valid_word = word_num&1;
    entry_size_per_index = (entry_size-(have_valid_word<<2))>>1;

    /*malloc  memory*/
    p_hw_buffer = mem_malloc(MEM_SYSTEM_MODULE, entry_size);
    if (NULL ==  p_hw_buffer)
    {
        DRV_DBG_INFO("DRV_SDB:No Memory.\n");
        return DRV_E_NO_MEMORY;
    }
    do
    {
        p_sw_buffer = (uint32*)(tcam_info.sw_addr+entry_id*tcam_info.entry_offset);
        DRV_SDB_IF_CONTINUE(have_valid_word && 0 == p_sw_buffer[word_num-1]);
        DRV_SDB_IF_CONTINUE(!have_valid_word && !DRV_IS_BIT_SET(p_sw_buffer[word_num-1], 31));

        if (DRV_IS_BIT_SET(flag, 2))
        {
            DRV_SDB_DUMP_FILE(pf, "  \nmem_id(%d) index(%u) value:\n", mem_id, entry_id);
            for (index = 0; index < (entry_size<<2); index++)
            {
                DRV_SDB_DUMP_FILE(pf, "  0x%08x ", p_sw_buffer[index]);
                if (7 == (index&7))
                {
                    DRV_SDB_DUMP_FILE(pf, "\n");
                }
            }
        }        
        if (DRV_IS_BIT_SET(flag, 0))
        {
            drv_usw_chip_read_sram_entry(lchip, ((uint64)oper_bmp<<32)|(mem_addr+entry_id*tcam_info.entry_offset), p_hw_buffer, entry_size);
            DRV_SDB_TCAM_XY2DM(p_hw_buffer, entry_size_per_index);
            DRV_SDB_TCAM_DMCHK(p_sw_buffer, entry_size_per_index);

            DRV_SDB_IF_CONTINUE(sal_memcmp(p_hw_buffer, p_sw_buffer, entry_size) == 0);
            if (DRV_IS_BIT_SET(flag, 1))
            {
                drv_usw_chip_write_sram_entry(lchip, ((uint64)oper_bmp<<32)|(mem_addr+entry_id*tcam_info.entry_offset), p_sw_buffer, entry_size);
            }
            DRV_SDB_BUFFER_DUMP("hw_buffer: ", p_hw_buffer, entry_size);
            DRV_SDB_BUFFER_DUMP("sw_buffer: ", p_sw_buffer, entry_size);
            DRV_SDB_DUMP_FILE(pf, "Mem check fail!, index:%u\n", entry_id);
            *cmp_result = TRUE;
        }
    }while(++entry_id < entry_num);
    mem_free(p_hw_buffer);
    return DRV_E_NONE;
}

int32
_drv_sdb_check_dynamic(uint8 lchip, uint8 mem_id, uint8 oper_bmp, uint8 flag, uint8* cmp_result, sal_file_t pf)
{
    uint32   entry_id = 0;
    uintptr  mapped_index;
    uint32   entry_num = 0;
    uint32   mem_size = 0, entry_size = 0;
    uint32*  hw_addr_array = &DRV_MEM_INFO(lchip, mem_id).addr_3w;
    uint32   hw_addr = 0;
    uint32   index = 0;
    uint8*   sw_addr = 0;
    uint32   entry_offset = 0;
    uint8    busrt_op = 0;
    uint8    sram_type = 0;
    uint32*  p_hw_buffer = NULL;
    uint8*   p_sw_buffer = NULL;
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    uint8    is_flow_tcam_ad = ((p_drv_master[lchip]->dev_type == DRV_TSINGMA) && mem_id >= DRV_FTM_TCAM_AD0 && mem_id <= DRV_FTM_TCAM_AD18);
    uint8    is_lpm_tcam_ad = ((p_drv_master[lchip]->dev_type == DRV_TSINGMA) && mem_id >= DRV_FTM_LPM_TCAM_AD0 && mem_id <= DRV_FTM_LPM_TCAM_AD11);
    uintptr  offset = 0;
    uint8    dp_id = (oper_bmp>>1)&0x1;
    
    drv_usw_get_memory_size(lchip, mem_id, &mem_size);
    sw_addr = p_sdb->dynamic_tbl[mem_id] + (dp_id ? mem_size<<2 : 0);
    DRV_SDB_DUMP_FILE(pf, "SRAM checking[lchip:%d][mem_id:%u][SDB Address:%p]...\n", lchip, mem_id, (uint8*)sw_addr);

    //drv_usw_ftm_get_sram_info(lchip, mem_id, &hw_addr, &entry_num, &entry_size);
    entry_size = DRV_MEM_ENTRY_SIZE(lchip, mem_id);
    if (entry_size == 0 || 0 == drv_usw_ftm_sram_use_sdb(lchip, mem_id))
    {
        return DRV_E_NONE;
    }
    DRV_IF_ERROR_RETURN(drv_usw_ftm_get_sram_type(lchip, mem_id, &sram_type));
    if (DRV_FROM_TMM(lchip) && DRV_FTM_SRAM_TBL_MPLS_HASH_KEY == sram_type)
    {
        hw_addr_array = &DRV_MEM_INFO(lchip, mem_id).addr_6w;
    }
    
    DRV_SDB_ENTRY_SIZE_ALINE(entry_size, entry_offset);
    entry_num = mem_size / entry_size;
#ifdef EMULATION_ENV
    entry_num = 32;
#endif

    /*malloc  memory*/
    p_hw_buffer = mem_malloc(MEM_SYSTEM_MODULE, entry_size);
    if (NULL ==  p_hw_buffer)
    {
        DRV_DBG_INFO("DRV_SDB:No Memory.\n");
        return DRV_E_NO_MEMORY;
    }

    do
    {
        mapped_index = (is_flow_tcam_ad && p_drv_master[lchip]->p_mem_info[mem_id].index_map)?\
            ((p_drv_master[lchip]->p_mem_info[mem_id].index_map[entry_id<<1])>>1):\
            ((is_lpm_tcam_ad && p_drv_master[lchip]->p_mem_info[mem_id].index_map) ? \
                p_drv_master[lchip]->p_mem_info[mem_id].index_map[entry_id] : entry_id);
        hw_addr = hw_addr_array[DRV_MEM_ADDR_SEL(lchip, mem_id)] + busrt_op;
        offset = mapped_index*entry_offset;

        p_sw_buffer = sw_addr + _drv_sdb_get_entry_offset(lchip, ((mem_id<<24) | sram_type), entry_id, entry_size, p_sdb);
        if (DRV_IS_BIT_SET(flag, 2))
        {
            sal_memset(p_hw_buffer, 0, entry_size);
            DRV_SDB_IF_CONTINUE(0 == sal_memcmp(p_hw_buffer, p_sw_buffer, entry_size));
            DRV_SDB_DUMP_FILE(pf, "  \nmem_id(%d) index(%u) value:\n", mem_id, entry_id);
            for (index = 0; index < (entry_size<<2); index++)
            {
                DRV_SDB_DUMP_FILE(pf, "  0x%08x ", p_sw_buffer[index]);
                if (7 == (index&7))
                {
                    DRV_SDB_DUMP_FILE(pf, "\n");
                }
            }
        }

        /*bit0:check, bit1:recover, bit2:dump*/
        if (DRV_IS_BIT_SET(flag, 0))
        {
            drv_usw_chip_read_sram_entry(lchip, ((uint64)oper_bmp<<32)|(hw_addr+offset), p_hw_buffer, entry_size);
            DRV_SDB_IF_CONTINUE(sal_memcmp(p_hw_buffer, p_sw_buffer, entry_size) == 0);
            if (DRV_IS_BIT_SET(flag, 1))
            {
                drv_usw_chip_write_sram_entry(lchip, ((uint64)oper_bmp<<32)|(hw_addr+offset), (uint32*)p_sw_buffer, entry_size);
            }
            DRV_SDB_BUFFER_DUMP("hw_buffer: ", p_hw_buffer, entry_size);
            DRV_SDB_BUFFER_DUMP("sw_buffer: ", p_sw_buffer, entry_size);
            DRV_SDB_DUMP_FILE(pf, "Mem check fail!, index:%u, sdb entry(%p)\n", entry_id, p_sw_buffer);
            *cmp_result = TRUE;
        }
    }while(++entry_id < entry_num);
    mem_free(p_hw_buffer);
    return DRV_E_NONE;
}


int32
drv_sdb_check_per_ram(uint8 lchip, uint8 mem_id, uint8 flag, uint8* cmp_result, sal_file_t pf)
{
    uint8    mem_type      = 0;
    uint8    order = 0;
    uint8    type  = 0;
    uint8    oper_bmp  = 0;
    uint32   sram_type = 0;
    uint8    tbl_type = 0; /* 0: PP->core 1: core 2: other */
    uint32   sram_tbl_a[200] = {0};
    uint8    share_tbl_num  = 0;
    uint8    per_tbl_entry_num = 0;
    drv_sdb_t* p_sdb = (drv_sdb_t*)(g_sdb_master[lchip]);

    mem_type = _drv_sdb_get_ram_type(lchip, mem_id, FALSE);
    if (mem_type == DRV_FTM_MEM_DYNAMIC)
    {
        if (p_sdb->dynamic_tbl[mem_id] == NULL)
        {
            return DRV_E_NONE;
        }
        /*sharebuffer 0-3 fdb not support recover*/
        drv_sdb_get_mem_id_info(lchip, mem_id,&order,&type);
        if ((DRV_FTM_MEM_SHARE_MEM == type) && (order < 4))
        {
            return DRV_E_NONE;
        }
        /*aging and learning ram do not support*/
        if (drv_usw_ftm_ram_with_chip_op(lchip, mem_id))
        {
            return DRV_E_NONE;
        }

        if (mem_id < DRV_FTM_EDRAM_MAX)
        {
            sram_type = drv_usw_ftm_memid_2_table(lchip, mem_id);
            drv_usw_ftm_get_sram_tbl_id(lchip, sram_type, sram_tbl_a, &share_tbl_num, &per_tbl_entry_num);
            tbl_type = (TABLE_ENTRY_TYPE(lchip, sram_tbl_a[0]) == DRV_FEATURE_MODE_PER_CORE) ? 1 : 0;
        }
        
        if (1 == tbl_type)
        {
            oper_bmp = p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1];
        }
        else
        {
            oper_bmp = p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1] | p_drv_master[lchip]->pp_bmp[g_drv_chip[lchip].pp_id];
        }
        
        if (mem_id >= DRV_FTM_SRAM47 && mem_id <= DRV_FTM_SRAM54)
        {
            /* DP 0 */
            oper_bmp = (oper_bmp & (~(3))) | 1;
            DRV_IF_ERROR_RETURN(_drv_sdb_check_dynamic(lchip, mem_id, oper_bmp, flag, cmp_result, pf));
            /* DP 1 */
            oper_bmp = (oper_bmp & (~(3))) | 2;
            DRV_IF_ERROR_RETURN(_drv_sdb_check_dynamic(lchip, mem_id, oper_bmp, flag, cmp_result, pf));
        }
        else
        {
            DRV_IF_ERROR_RETURN(_drv_sdb_check_dynamic(lchip, mem_id, oper_bmp, flag, cmp_result, pf));
        }
    }
    else
    {
        oper_bmp = p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1] | p_drv_master[lchip]->pp_bmp[g_drv_chip[lchip].pp_id];
        DRV_IF_ERROR_RETURN(_drv_sdb_check_tcam(lchip, mem_id, oper_bmp, flag, cmp_result, pf));
    }

    return DRV_E_NONE;
}


int32
drv_sdb_set_stop_store(uint8 lchip, uint8 enable)
{
    drv_sdb_t* p_sdb = NULL;

    DRV_SDB_INIT_CHECK(lchip);
    p_sdb = g_sdb_master[lchip];
    if (NULL == p_sdb)
    {
        DRV_DBG_INFO("DRV_MEM_DB:can not set simluation-config,becasuse drv_mem_db do not init");
        return DRV_E_NONE;
    }

    p_sdb->sdb_en = enable ? FALSE : TRUE;
    return DRV_E_NONE;
}

#define ___SDB_INIT___

typedef struct drv_sdb_ram_info_s
{
    uint32 ram_id    :8;
    uint32 ram_size  :24;
}drv_sdb_ram_info_t;
#define DRV_SDB_MAX_MEM_NUM_PER_TBL     16

#if (SDB_TIMESTAMP != SDB_MODE)
STATIC INLINE int32
_drv_sdb_init_ram(uint8 lchip, tbls_id_t tbl_id, uint8 ram_base, uint8 ram_max, uint32* tbl_bmp, uint32* dyn_mem_bmp, uint32* p_mem_offset, uint8 ext_type, uint8 pmem_en)
{
    uint32 local_size = 0, mem_size = 0;
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    uint8  ramid = ram_base;
    uint8  p_ram_index = 0;
    uint8  first_ram = 1;
    uint8  size_shift = (ext_type == DRV_SDB_TBL_SNAKE)? (1): (0);
    drv_sdb_ram_info_t* ram_info = NULL;

    ram_info = mem_malloc(MEM_SYSTEM_MODULE, sizeof(drv_sdb_ram_info_t) * DRV_SDB_MAX_MEM_NUM_PER_TBL);
    if (!ram_info)
    {
        return DRV_E_NO_MEMORY;
    }
    sal_memset(ram_info, 0, sizeof(drv_sdb_ram_info_t) * DRV_SDB_MAX_MEM_NUM_PER_TBL);
    ramid = ram_base;
    do {
        DRV_SDB_IF_CONTINUE(!DRV_BMP_ISSET(tbl_bmp, ramid-ram_base));
        local_size = 0;
        drv_usw_get_memory_size(lchip, ramid, &local_size);
        DRV_SDB_IF_CONTINUE(local_size == 0 || FALSE == drv_usw_ftm_sram_use_sdb(lchip, ramid));
        local_size = local_size >> size_shift;

        if (DRV_BMP_ISSET(dyn_mem_bmp, ramid))  /*have alloced, same table share one memory*/
        {
            DRV_SDB_ADDR_BASE(tbl_id) = (uint8*)p_sdb->dynamic_tbl[ramid];
            break;
        }
        else
        {
            p_sdb->dynamic_tbl[ramid] = (uint8*)(p_sdb->mem_addr + (*p_mem_offset) + mem_size);
            if (first_ram)
            {          
                DRV_SDB_ADDR_BASE(tbl_id) = (uint8*)p_sdb->dynamic_tbl[ramid];
                p_ram_index = 0;
                first_ram = 0;
            }
            else
            {
                p_ram_index++;
            }
            ram_info[p_ram_index].ram_id = ramid;
            ram_info[p_ram_index].ram_size = local_size;
            mem_size += local_size;
            DRV_BMP_SET(dyn_mem_bmp, ramid);
        }
    }while(++ramid < ram_max);
    size_shift = (ext_type == DRV_SDB_TBL_DP)? 1:size_shift;
    mem_size = mem_size << size_shift;
    if (!pmem_en && mem_size)
    {
        DRV_SDB_ADDR_BASE(tbl_id) = (uint8*)mem_malloc(MEM_SYSTEM_MODULE, mem_size);
        if (!DRV_SDB_ADDR_BASE(tbl_id))
        {
            mem_free(ram_info);
            return DRV_E_NO_MEMORY;
        }
        sal_memset(DRV_SDB_ADDR_BASE(tbl_id), 0, mem_size);
        p_sdb->dynamic_tbl[ram_info[0].ram_id] = DRV_SDB_ADDR_BASE(tbl_id);
        p_ram_index = 1;
        do{
            if (ram_info[p_ram_index].ram_size == 0) { break; }
            p_sdb->dynamic_tbl[ram_info[p_ram_index].ram_id] = p_sdb->dynamic_tbl[ram_info[p_ram_index-1].ram_id] + ram_info[p_ram_index-1].ram_size;
        }while(++p_ram_index < DRV_SDB_MAX_MEM_NUM_PER_TBL);
    }
    (*p_mem_offset) += mem_size;
    mem_free(ram_info);
    return 0;
}
#else
STATIC INLINE int32
_drv_sdb_init_ram(uint8 lchip, tbls_id_t tbl_id, uint8 ram_base, uint8 ram_max, uint32* tbl_bmp, uint32* dyn_mem_bmp, uint32* p_mem_offset, uint8 ext_type, uint8 pmem_en)
{
    uint32  local_size = 0, mem_size = 0;
    uint32  ts_mem_size = 0;
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    drv_sdb_ts_hdr_t* p_ts_hdr = NULL;
    uint8  size_shift = (ext_type == DRV_SDB_TBL_SNAKE)? (1): (0);
    uint8  ramid = ram_base;
    uint8  p_ram_index = 0;
    uint8  first_ram = 1;
    uint8  tcam_ad_shift = 0;
    drv_sdb_ram_info_t* ram_info = NULL;
    uint32 ts_offset = 0;

    ram_info = mem_malloc(MEM_SYSTEM_MODULE, sizeof(drv_sdb_ram_info_t) * DRV_SDB_MAX_MEM_NUM_PER_TBL);
    if (!ram_info)
    {
        return DRV_E_NO_MEMORY;
    }
    sal_memset(ram_info, 0, sizeof(drv_sdb_ram_info_t) * DRV_SDB_MAX_MEM_NUM_PER_TBL);
    do {
        DRV_SDB_IF_CONTINUE(!DRV_BMP_ISSET(tbl_bmp, ramid-ram_base));
        local_size = 0;
        drv_usw_get_memory_size(lchip, ramid, &local_size);
        DRV_SDB_IF_CONTINUE(local_size == 0 || FALSE == drv_usw_ftm_sram_use_sdb(lchip, ramid));
        local_size = local_size >> size_shift;

        if (DRV_BMP_ISSET(dyn_mem_bmp, ramid))  /*have alloced, same table share one memory*/
        {
            DRV_SDB_ADDR_BASE(tbl_id) = p_sdb->dynamic_tbl[ramid];
            if (DRV_SDB_ADDR_BASE(tbl_id))
            {
                p_ts_hdr = (drv_sdb_ts_hdr_t*)(DRV_SDB_ADDR_BASE(tbl_id) - sizeof(drv_sdb_ts_hdr_t));
            }
            first_ram = 0xFF;
            break;
        }
        else
        {
            p_sdb->dynamic_tbl[ramid] = (uint8*)(p_sdb->mem_addr + (*p_mem_offset) + mem_size);
            if (first_ram)
            {
                p_sdb->dynamic_tbl[ramid] += sizeof(drv_sdb_ts_hdr_t);
                DRV_SDB_ADDR_BASE(tbl_id) = p_sdb->dynamic_tbl[ramid];
                p_ram_index = 0;
                first_ram = 0;
                mem_size += sizeof(drv_sdb_ts_hdr_t);
            }
            else
            {
                p_ram_index++;
            }
            ram_info[p_ram_index].ram_id = ramid;
            ram_info[p_ram_index].ram_size = local_size;
            if (ext_type == DRV_SDB_TBL_TCAM_AD)
            {
                tcam_ad_shift = ((p_drv_master[lchip]->dev_type == DRV_TSINGMA) && TCAM_KEY_MODULE(lchip, tbl_id) == TCAM_MODULE_ACL) ? 1 : 0;
                ts_mem_size += (TCAM_END_INDEX(lchip, tbl_id, ramid-ram_base)-TCAM_START_INDEX(lchip, tbl_id, ramid-ram_base)+1) * (DRV_SDB_TS_SIZE << tcam_ad_shift);
            }
            else if (tbl_id == DsFwd_t || tbl_id == DsFwdDualHalf_t || tbl_id == DsFwdHalf_t)
            {
                ts_mem_size += (DYNAMIC_END_INDEX(lchip, tbl_id, ramid)-DYNAMIC_START_INDEX(lchip, tbl_id, ramid)+1) * DRV_SDB_TS_SIZE * 2;
            }
            else
            {
                ts_mem_size += (DYNAMIC_END_INDEX(lchip, tbl_id, ramid)-DYNAMIC_START_INDEX(lchip, tbl_id, ramid)+1) * DRV_SDB_TS_SIZE;
            }
            ram_info[p_ram_index].ram_id = ramid;
            ram_info[p_ram_index].ram_size = local_size;
            mem_size += local_size;
            DRV_BMP_SET(dyn_mem_bmp, ramid);
        }
    }while(++ramid < ram_max);        
    ts_offset = p_ts_hdr?p_ts_hdr->ent_ts_offset:((mem_size-sizeof(drv_sdb_ts_hdr_t)));
    size_shift = (ext_type == DRV_SDB_TBL_DP)? 1:size_shift;  /* DP tbl per memory get size is equal with memory size */
    mem_size = (mem_size + ts_mem_size) << size_shift;
    if (!pmem_en && mem_size)
    {
        DRV_SDB_ADDR_BASE(tbl_id) = (uint8*)mem_malloc(MEM_SYSTEM_MODULE, mem_size);
        if (!DRV_SDB_ADDR_BASE(tbl_id))
        {
            mem_free(ram_info);
            return DRV_E_NO_MEMORY;
        }
        sal_memset(DRV_SDB_ADDR_BASE(tbl_id), 0, mem_size);
        DRV_SDB_ADDR_BASE(tbl_id) += sizeof(drv_sdb_ts_hdr_t);
        p_sdb->dynamic_tbl[ram_info[0].ram_id] = DRV_SDB_ADDR_BASE(tbl_id);
        p_ram_index = 1;
        do{
            if (ram_info[p_ram_index].ram_size == 0) { break; }
            p_sdb->dynamic_tbl[ram_info[p_ram_index].ram_id] = p_sdb->dynamic_tbl[ram_info[p_ram_index-1].ram_id] + ram_info[p_ram_index-1].ram_size;
        }while(++p_ram_index < DRV_SDB_MAX_MEM_NUM_PER_TBL);
    }
    if (DRV_SDB_ADDR_BASE(tbl_id))
    {
        p_ts_hdr = (drv_sdb_ts_hdr_t*)(DRV_SDB_ADDR_BASE(tbl_id) - sizeof(drv_sdb_ts_hdr_t));
        p_ts_hdr->ent_ts_offset = ts_offset;
    }
    (*p_mem_offset) += mem_size;
    mem_free(ram_info);
    return 0;
}
#endif

int32
_drv_sdb_init_static_tbl(uint8 lchip, uint32* p_mem_offset, drv_ser_global_cfg_t* p_cfg, uint8 pmem_en)
{
    tbls_id_t tbl_id = 0;
    uint32  tbl_entry_size = 0;
    uint32  tbl_max_size = 0;
    uint32  tbl_max_mem  = 0;
    uint32  mem_offset = *p_mem_offset;
#if (SDB_TIMESTAMP == SDB_MODE)
    drv_sdb_ts_hdr_t* p_ts_hdr = NULL;
#endif
    drv_sdb_t* p_sdb = (drv_sdb_t*)(g_sdb_master[lchip]);
    uint8 pp_base = drv_vchip_get_pp_base(lchip);
    uint8 tmp_chip = 0;

    tmp_chip = (lchip > (pp_base + p_drv_master[lchip]->core_pp_num))? 
                (pp_base + p_drv_master[lchip]->core_pp_num): pp_base;
    for (tbl_id = 0; tbl_id < MaxTblId_t; tbl_id++ )
    {
        /*non-static table*/
        DRV_SDB_IF_CONTINUE(_drv_sdb_get_tbl_type(lchip, tbl_id) != DRV_FTM_TABLE_STATIC);

        /*no sdb capability*/
        DRV_SDB_IF_CONTINUE(!DRV_SDB_MODE_VALID(tbl_id));

        /*table size is 0*/
        tbl_entry_size = DRV_TBL_TCAM_MEM(tbl_id) ? TABLE_ENTRY_OFFSET(lchip, tbl_id) : TABLE_ENTRY_SIZE(lchip, tbl_id);
        tbl_max_size = ((TABLE_MAX_INDEX(lchip, tbl_id)) * tbl_entry_size);
        DRV_SDB_IF_CONTINUE(tbl_max_size == 0);

        /*store sdb addr to table info*/
        if ((lchip != pp_base) && (lchip != pp_base + p_drv_master[lchip]->core_pp_num) && TABLE_ENTRY_TYPE(lchip, tbl_id) == DRV_FEATURE_MODE_PER_CORE)
        {
            DRV_SDB_ADDR_BASE(tbl_id) = g_sdb_master[tmp_chip]->static_tbl[tbl_id];
            continue;
        }
        else if (lchip != pp_base && DRV_TBL_FEA_MOD(tbl_id) == DRV_FEATURE_MODE_PER_CORE && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_CORE)
        {
            DRV_SDB_ADDR_BASE(tbl_id) = g_sdb_master[pp_base]->static_tbl[tbl_id];
            continue;
        }
        if (pmem_en)
        {
            p_sdb->static_tbl[tbl_id] = (uint8*)p_sdb->mem_addr + mem_offset;
        }
        else
        {
            #if (SDB_TIMESTAMP == SDB_MODE)
            tbl_max_mem = sizeof(drv_sdb_ts_hdr_t) + ((tbl_max_size + ((TABLE_MAX_INDEX(lchip, tbl_id)) * DRV_SDB_TS_SIZE)) <<
                (DRV_FEATURE_MODE_PER_DP == DRV_TBL_FEA_MOD(tbl_id) || DRV_FEATURE_MODE_PEER_DP == DRV_TBL_FEA_MOD(tbl_id)));
            #else
            tbl_max_mem = tbl_max_size << (DRV_FEATURE_MODE_PER_DP == DRV_TBL_FEA_MOD(tbl_id) || DRV_FEATURE_MODE_PEER_DP == DRV_TBL_FEA_MOD(tbl_id));
            #endif
            p_sdb->static_tbl[tbl_id] = (uint8*)mem_malloc(MEM_SYSTEM_MODULE, tbl_max_mem);
            if (!p_sdb->static_tbl[tbl_id])
            {
                return DRV_E_NO_MEMORY;
            }
            sal_memset(p_sdb->static_tbl[tbl_id], 0, tbl_max_mem);
        }

#if (SDB_TIMESTAMP == SDB_MODE)
        p_ts_hdr = (drv_sdb_ts_hdr_t*)DRV_SDB_ADDR_BASE(tbl_id);
        p_ts_hdr->ent_ts_offset = tbl_max_size;
        p_sdb->static_tbl[tbl_id] += sizeof(drv_sdb_ts_hdr_t);
        tbl_max_mem =sizeof(drv_sdb_ts_hdr_t) + ((tbl_max_size+ (TABLE_MAX_INDEX(lchip, tbl_id)) * DRV_SDB_TS_SIZE) <<
            (DRV_FEATURE_MODE_PER_DP == DRV_TBL_FEA_MOD(tbl_id) || DRV_FEATURE_MODE_PEER_DP == DRV_TBL_FEA_MOD(tbl_id)));
#else
        tbl_max_mem = tbl_max_size << (DRV_FEATURE_MODE_PER_DP == DRV_TBL_FEA_MOD(tbl_id) || DRV_FEATURE_MODE_PEER_DP == DRV_TBL_FEA_MOD(tbl_id));
#endif

        mem_offset += tbl_max_mem;
   }
   *p_mem_offset = mem_offset;
   return DRV_E_NONE;
}

int32
_drv_sdb_init_dynamic_tbl(uint8 lchip, uint32* p_mem_offset, uint8 pmem_en)
{
    uint8 tbl_type = 0;
    uint8 ext_type = 0;
    uint8 pp_base = drv_vchip_get_pp_base(lchip);
    uint8 tmp_chip = 0;
    uint32 dyn_mem_bmp[(DRV_FTM_MAX_ID+31)/32] = {0};
    tbls_id_t tbl_id = 0;
    drv_sdb_t* p_sdb = (drv_sdb_t*)(g_sdb_master[lchip]);
    uint32 mem_offset = *p_mem_offset;
    uint32 old_mem_offset = 0;
    uint32 snake_ram_size = 0;
    uint32 snake_ram_size_l1 = 0;
#if (SDB_TIMESTAMP == SDB_MODE)
    drv_sdb_ts_hdr_t* p_ts_hdr = NULL;
    uint32 snake_ent_ts_offset = 0;
#endif

    tmp_chip = (lchip > (pp_base + p_drv_master[lchip]->core_pp_num))? 
                (pp_base + p_drv_master[lchip]->core_pp_num): pp_base;
    for (tbl_id = 0; tbl_id < MaxTblId_t; tbl_id++ )    /*traverse all table id*/
    {
        tbl_type = _drv_sdb_get_tbl_type(lchip, tbl_id);
        DRV_SDB_IF_CONTINUE(tbl_type == DRV_FTM_TABLE_STATIC);
        DRV_SDB_IF_CONTINUE(!DRV_SDB_MODE_VALID(tbl_id));
        DRV_SDB_IF_CONTINUE(!TABLE_EXT_INFO_PTR(lchip, tbl_id));
        ext_type = (
            tbl_id == DsNeoLpmIpv4Bit32Snake_t     || tbl_id == DsNeoLpmIpv6Bit64Snake_t     ||
            tbl_id == DsNeoLpmIpv6Bit128Snake_t    || tbl_id == DsNeoLpmIpv4Bit32SnakeExt_t  ||
            tbl_id == DsNeoLpmIpv6Bit64SnakeExt_t  || tbl_id == DsNeoLpmMemorySnakeP1_t      ||
            tbl_id == DsNeoLpmIpv4Bit32Snake1_t    || tbl_id == DsNeoLpmIpv6Bit64Snake1_t    ||
            tbl_id == DsNeoLpmIpv6Bit128Snake1_t   || tbl_id == DsNeoLpmIpv4Bit32SnakeExt1_t ||
            tbl_id == DsNeoLpmIpv6Bit64SnakeExt1_t  || tbl_id == DsNeoLpmMemorySnakeP2_t     ||
            tbl_id == DsNeoLpmIpv4Bit32SnakeExt0_t  || tbl_id == DsNeoLpmIpv4Bit32Snake0_t   ||
            tbl_id == DsNeoLpmIpv6Bit64Snake0_t    || tbl_id == DsNeoLpmIpv6Bit128Snake0_t   ||
            tbl_id == DsNeoLpmL0Ipv4Bit32Snake_t  || tbl_id == DsNeoLpmL0Ipv6Bit128Snake_t   ||
            tbl_id == DsNeoLpmL0Ipv6Bit64Snake_t  || tbl_id == DsNeoLpmL0Ipv4Bit32Snake0_t   ||
            tbl_id == DsNeoLpmL0Ipv6Bit128Snake0_t || tbl_id == DsNeoLpmL0Ipv6Bit64Snake0_t  ||
            tbl_id == DsNeoLpmL0MemorySnakeP1_t  || tbl_id == DsNeoLpmL0Ipv4Bit32Snake1_t    ||
            tbl_id == DsNeoLpmL0Ipv6Bit128Snake1_t || tbl_id == DsNeoLpmL0Ipv6Bit64Snake1_t  ||
            tbl_id == DsNeoLpmL0MemorySnakeP2_t) ? DRV_SDB_TBL_SNAKE : DRV_SDB_TBL_DYNAMIC;
        ext_type = (
            tbl_id == DsXSecRxL2BasicHashKey_t || tbl_id == DsXSecRxL2MacsecHashKey_t ||
            tbl_id == DsXSecRxL3L4V4HashKey_t || tbl_id == DsXSecRxL3L4V6HashKey_t ||
            tbl_id == DsXSecRxSpiHashKey_t || tbl_id == DsXSecTxL2BasicHashKey_t ||
            tbl_id == DsXSecTxL3L4V4HashKey_t || tbl_id == DsXSecTxL3L4V6HashKey_t ||
            tbl_id == DsXSecTxSpiHashKey_t)? DRV_SDB_TBL_DP: ext_type;

        if ((lchip != pp_base) && (lchip != pp_base + p_drv_master[lchip]->core_pp_num) && TABLE_ENTRY_TYPE(lchip, tbl_id) == DRV_FEATURE_MODE_PER_CORE)
        {
            DRV_SDB_ADDR_BASE(tbl_id) = g_sdb_master[tmp_chip]->static_tbl[tbl_id];
            continue;
        }
        else if (lchip != pp_base && DRV_TBL_FEA_MOD(tbl_id) == DRV_FEATURE_MODE_PER_CORE && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_CORE)
        {
            DRV_SDB_ADDR_BASE(tbl_id) = g_sdb_master[pp_base]->static_tbl[tbl_id];
            continue;
        }

        old_mem_offset = mem_offset;
        switch(TABLE_EXT_INFO_TYPE(lchip, tbl_id))
        {
             case DRV_TABLE_TYPE_TCAM:
            {
                continue;
            }
            case DRV_TABLE_TYPE_TCAM_AD:
            {
                if (TCAM_KEY_MODULE(lchip, tbl_id) == TCAM_MODULE_LPM)
                {
                    DRV_IF_ERROR_RETURN(_drv_sdb_init_ram(lchip, tbl_id, DRV_FTM_LPM_TCAM_AD0, (DRV_FTM_LPM_TCAM_AD0 + DRV_CONST(DRV_MAX_LPM_TCAM_NUM)), TCAM_BITMAP(lchip, tbl_id), dyn_mem_bmp, &mem_offset, DRV_SDB_TBL_TCAM_AD, pmem_en));
                }
                else
                {
                    DRV_IF_ERROR_RETURN(_drv_sdb_init_ram(lchip, tbl_id, DRV_FTM_TCAM_AD0, (DRV_FTM_TCAM_AD0 + DRV_CONST(DRV_MAX_NOR_TCAM_NUM)), TCAM_BITMAP(lchip, tbl_id), dyn_mem_bmp, &mem_offset, DRV_SDB_TBL_TCAM_AD, pmem_en));
                }
                p_sdb->catch_mem_dynamic_size += mem_offset - old_mem_offset;
                break;
            }
            case DRV_TABLE_TYPE_TCAM_LPM_AD:
            case DRV_TABLE_TYPE_TCAM_NAT_AD:
            {
                DRV_IF_ERROR_RETURN(_drv_sdb_init_ram(lchip, tbl_id, DRV_FTM_LPM_TCAM_AD0, (DRV_FTM_LPM_TCAM_AD0 + DRV_CONST(DRV_MAX_LPM_TCAM_NUM)), TCAM_BITMAP(lchip, tbl_id), dyn_mem_bmp, &mem_offset, DRV_SDB_TBL_TCAM_AD, pmem_en));
                p_sdb->catch_mem_dynamic_size += mem_offset - old_mem_offset;
                break;
            }
            case DRV_TABLE_TYPE_LPM_TCAM_IP:
            case DRV_TABLE_TYPE_LPM_TCAM_NAT:
            {
                continue;
            }
            case DRV_TABLE_TYPE_STATIC_TCAM_KEY:
            {
                continue;
            }
            case DRV_TABLE_TYPE_DYNAMIC:
            case DRV_TABLE_TYPE_MIXED:
            {
                DRV_IF_ERROR_RETURN(_drv_sdb_init_ram(lchip, tbl_id, DRV_FTM_SRAM0, DRV_FTM_EDRAM_MAX,
                                 DYNAMIC_BITMAP(lchip, tbl_id), dyn_mem_bmp, &mem_offset, ext_type, pmem_en));
                if ((((p_drv_master[lchip]->dev_type == DRV_TSINGMA_MX) || (p_drv_master[lchip]->dev_type == DRV_TSINGMA_GX)) && 0 == snake_ram_size && DRV_SDB_TBL_SNAKE == ext_type) ||
                   ((p_drv_master[lchip]->dev_type >= DRV_ARCTIC) && DsNeoLpmIpv4Bit32SnakeExt0_t == tbl_id))
                {
                    snake_ram_size = mem_offset - old_mem_offset;
                    p_sdb->catch_mem_dynamic_size += snake_ram_size;
                }
                else if ((p_drv_master[lchip]->dev_type >= DRV_ARCTIC) && DsNeoLpmIpv4Bit32Snake0_t == tbl_id)
                {
                    snake_ram_size_l1 = mem_offset - old_mem_offset;
                    p_sdb->catch_mem_dynamic_size += snake_ram_size_l1;
                }
                else
                {
                    p_sdb->catch_mem_dynamic_size += mem_offset - old_mem_offset;
                }
                break;
            }
            case DRV_TABLE_TYPE_NORMAL:
            case DRV_TABLE_TYPE_DESC:
            case DRV_TABLE_TYPE_DBG:
            case DRV_TABLE_TYPE_INVALID:
                break;
        }
    }
    if (((p_drv_master[lchip]->dev_type == DRV_TSINGMA_MX) || (p_drv_master[lchip]->dev_type == DRV_TSINGMA_GX)) && snake_ram_size)
    {
        /*update snake 1 mem addr*/
        DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t)    = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake_t) + (snake_ram_size>>1);
        DRV_SDB_ADDR_BASE(DsNeoLpmIpv6Bit64Snake1_t)    = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t);
        DRV_SDB_ADDR_BASE(DsNeoLpmIpv6Bit128Snake1_t)   = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t);
        DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32SnakeExt1_t) = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t);
        DRV_SDB_ADDR_BASE(DsNeoLpmIpv6Bit64SnakeExt1_t) = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t);
        DRV_SDB_ADDR_BASE(DsNeoLpmMemorySnakeP2_t)      = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t);
#if (SDB_TIMESTAMP == SDB_MODE)
        /*update snake 0*/
        p_ts_hdr = (drv_sdb_ts_hdr_t*)(DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake_t) - sizeof(drv_sdb_ts_hdr_t));
        snake_ent_ts_offset = p_ts_hdr->ent_ts_offset;
        /*update snake 1*/
        p_ts_hdr = (drv_sdb_ts_hdr_t*)(DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t) - sizeof(drv_sdb_ts_hdr_t));
        p_ts_hdr->ent_ts_offset = snake_ent_ts_offset;
#endif
    }
    if ((p_drv_master[lchip]->dev_type >= DRV_ARCTIC) && snake_ram_size)
    {
        /* level 0 update snake 1 mem addr */
        DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32SnakeExt1_t)  = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32SnakeExt0_t) + (snake_ram_size>>1);
        DRV_SDB_ADDR_BASE(DsNeoLpmL0Ipv4Bit32Snake1_t)   = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32SnakeExt1_t);
        DRV_SDB_ADDR_BASE(DsNeoLpmL0Ipv6Bit128Snake1_t)  = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32SnakeExt1_t);
        DRV_SDB_ADDR_BASE(DsNeoLpmL0Ipv6Bit64Snake1_t)   = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32SnakeExt1_t);
        DRV_SDB_ADDR_BASE(DsNeoLpmL0MemorySnakeP2_t)     = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32SnakeExt1_t);
        
        /* level 1 update snake 1 mem addr */
        DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t)     = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake0_t) + (snake_ram_size_l1>>1);
        DRV_SDB_ADDR_BASE(DsNeoLpmIpv6Bit64Snake1_t)     = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t);
        DRV_SDB_ADDR_BASE(DsNeoLpmIpv6Bit128Snake1_t)    = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t);
        DRV_SDB_ADDR_BASE(DsNeoLpmMemorySnakeP2_t)       = DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t);

#if (SDB_TIMESTAMP == SDB_MODE)
        /*level 0 update snake 0*/
        p_ts_hdr = (drv_sdb_ts_hdr_t*)(DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32SnakeExt0_t) - sizeof(drv_sdb_ts_hdr_t));
        snake_ent_ts_offset = p_ts_hdr->ent_ts_offset;
        /*level 0 update snake 1*/
        p_ts_hdr = (drv_sdb_ts_hdr_t*)(DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32SnakeExt1_t) - sizeof(drv_sdb_ts_hdr_t));
        p_ts_hdr->ent_ts_offset = snake_ent_ts_offset;
        /*level 1 update snake 0*/
        p_ts_hdr = (drv_sdb_ts_hdr_t*)(DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake0_t) - sizeof(drv_sdb_ts_hdr_t));
        snake_ent_ts_offset = p_ts_hdr->ent_ts_offset;
        /*level 1 update snake 1*/
        p_ts_hdr = (drv_sdb_ts_hdr_t*)(DRV_SDB_ADDR_BASE(DsNeoLpmIpv4Bit32Snake1_t) - sizeof(drv_sdb_ts_hdr_t));
        p_ts_hdr->ent_ts_offset = snake_ent_ts_offset;
#endif
    }
    *p_mem_offset = mem_offset;
    return DRV_E_NONE;
}

#define ___MEM_DB_READ___
int32
drv_sdb_read_from_hw(uint8 lchip, uint8 enable)
{
    drv_sdb_t* p_sdb = NULL;

    p_sdb = g_sdb_master[lchip];
    if (NULL != p_sdb)
    {
        p_sdb->read_tbl_from_hw = enable;
    }
    return DRV_E_NONE;
}

#define ___MEM_DB_INTERFACE___

#define DRV_SDB_MAX_TABLE_SIZE  512

int32
_drv_sdb_check_table_field(uint8 lchip, uint32 tbl_id, void* hw_buffer, void* sw_buffer, sal_file_t pf)
{
    int32  ret = 0;
    uint32 field_id = 0;
    static uint32 drv_ds_t1[32];
    static uint32 drv_ds_t2[32];
    do {
        if (0 == TABLE_FIELD_INFO_PTR(lchip, tbl_id)[field_id].bits)
        {
            continue;
        }
        drv_get_field(lchip, tbl_id, field_id, hw_buffer, drv_ds_t1);
        drv_get_field(lchip, tbl_id, field_id, sw_buffer, drv_ds_t2);
        if (0 != sal_memcmp(drv_ds_t1, drv_ds_t2, sizeof(drv_ds_t1)))
        {
            DRV_SDB_DUMP_FILE(pf, "  Table(%s) Field(%s) check fail! \n",
                              TABLE_NAME(lchip, tbl_id),
                              FIELD_NAME(lchip, tbl_id, field_id));
            ret = -1;
        }
    }while(++field_id < TABLE_FIELD_NUM(lchip, tbl_id));
    return ret;
}

int32
_drv_sdb_check_per_table(uint8 lchip, uint32 tbl_id, uint8 flag, sal_file_t pf)
{
    uint32 entry_id = 0;
    uint32 blknum = 0;
    uint32 local_idx = 0;
    uint32 tcam_tbl_id = tbl_id;
    uint32 cmd = 0;
    uint32 index = 0;
    uint8  oper_bmp = 0;
    uint16 entry_size = TABLE_ENTRY_SIZE(lchip, tbl_id);
    uint8  entry_size_word = entry_size >> 2;
    uint8  table_type = _drv_sdb_get_tbl_type(lchip, tbl_id);
    uint8  entry_num_each_idx = 0;
    uint8  check_fail = FALSE;
    uint8  step = 1;
    uint32* hw_buffer = NULL;
    uint32* sw_buffer = NULL;
    drv_io_tcam_db_t* p_tcam_db = NULL;

    if (TABLE_ENTRY_SIZE(lchip, tbl_id) > DRV_SDB_MAX_TABLE_SIZE)
    {
        DRV_DUMP_INFO("table(%s) exceed max size(%u)! \n", TABLE_NAME(lchip, tbl_id), TABLE_ENTRY_SIZE(lchip, tbl_id));
        return DRV_E_EXCEED_MAX_SIZE;
    }
    hw_buffer = mem_malloc(MEM_SYSTEM_MODULE, DRV_SDB_MAX_TABLE_SIZE);
    if (NULL == hw_buffer)
    {
        return DRV_E_NO_MEMORY;
    }

    switch(table_type)
    {
    case DRV_FTM_TABLE_DYNAMIC:
        entry_size = (TABLE_IOCTL_TYPE(lchip, tbl_id) == DRV_TBL_TYPE_DYN ||
                      TABLE_IOCTL_TYPE(lchip, tbl_id) == DRV_TBL_TYPE_DYN_MASK ||
                      TABLE_IOCTL_TYPE(lchip, tbl_id) == DRV_TBL_TYPE_DYN_LPM) ?
                      DYNAMIC_TABLE_UNIT_SIZE(lchip, tbl_id) : entry_size;
        step = TABLE_ENTRY_SIZE(lchip, tbl_id)/entry_size;
        break;
    case DRV_FTM_TABLE_TCAM_KEY:
        p_tcam_db = &p_drv_master[lchip]->drv_io_tcam_db[TCAM_KEY_DRV_TYPE(lchip, tbl_id)];
        entry_num_each_idx = TCAM_KEY_SIZE(lchip, tbl_id)/p_tcam_db->tbl_size;
        p_tcam_db->drv_tcam_get_block_info(lchip, tbl_id, 0, &blknum, &local_idx);
        local_idx = blknum << p_tcam_db->blk_shift;
        tcam_tbl_id = tbl_id;

        tbl_id = p_tcam_db->tcam_mem_tbl_id;
        entry_size = TABLE_ENTRY_OFFSET(lchip, tbl_id);
        break;
    case DRV_FTM_TABLE_STATIC:
        if (1 == DRV_TBL_TCAM_MEM(tbl_id))
        {
            return DRV_E_NONE;
        }
        //entry_size = 1 == DRV_GET_TBL_INFO_IO_CACHE(tbl_id) ? TABLE_ENTRY_OFFSET(lchip, tbl_id) : entry_size;
        break;
    default:
        mem_free(hw_buffer);
        return DRV_E_INVALID_TBL;
    }
    for (entry_id=0; entry_id<TABLE_MAX_INDEX(lchip, tcam_tbl_id); entry_id+=step)
    {
        oper_bmp = (p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1]|p_drv_master[lchip]->pp_bmp[g_drv_chip[lchip].pp_id]|1)&
                   (p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, tbl_id)]);
        sw_buffer = drv_sdb_read(lchip, tbl_id, entry_id+local_idx, entry_size, oper_bmp);
        if (table_type == DRV_FTM_TABLE_TCAM_KEY)
        {
            if ((DRV_IS_BIT_SET(entry_size_word, 0) && 0 == sw_buffer[entry_size_word-1]) ||
                (!DRV_IS_BIT_SET(entry_size_word, 0) && !DRV_IS_BIT_SET(sw_buffer[entry_size_word-1], 31)))
            {
                continue;
            }
        }
        if (DRV_IS_BIT_SET(flag, 2))
        {
            sal_memset(hw_buffer, 0, DRV_SDB_MAX_TABLE_SIZE);
            if (0 != sal_memcmp(hw_buffer, sw_buffer, TABLE_ENTRY_SIZE(lchip, tbl_id)))
            {
                DRV_SDB_DUMP_FILE(pf, "  \nTable(%d, %s) lchip(%d) index(%u) value:\n", tbl_id, TABLE_NAME(lchip, tbl_id), lchip, entry_id);
                for (index = 0; index < (entry_size<<2); index++)
                {
                    DRV_SDB_DUMP_FILE(pf, "  0x%08x ", sw_buffer[index]);
                    if (7 == (index&7))
                    {
                        DRV_SDB_DUMP_FILE(pf, "\n");
                    }
                }
            }
            else if ((p_drv_master[lchip]->dev_type >= DRV_ARCTIC) && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_DP && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PEER_DP)
            {
                continue;
            }
            else
            {
                /* DP1 */
                oper_bmp = (oper_bmp & (~(3))) | 2;
                sw_buffer = drv_sdb_read(lchip, tbl_id, entry_id+local_idx, entry_size, oper_bmp);
                sal_memset(hw_buffer, 0, DRV_SDB_MAX_TABLE_SIZE);
                DRV_SDB_IF_CONTINUE(0 == sal_memcmp(hw_buffer, sw_buffer, TABLE_ENTRY_SIZE(lchip, tbl_id)));
                DRV_SDB_DUMP_FILE(pf, "  \nTable(%d, %s) lchip(%d) index(%u) value:\n", tbl_id, TABLE_NAME(lchip, tbl_id), lchip, entry_id);
                for (index = 0; index < (entry_size<<2); index++)
                {
                    DRV_SDB_DUMP_FILE(pf, "  0x%08x ", sw_buffer[index]);
                    if (7 == (index&7))
                    {
                        DRV_SDB_DUMP_FILE(pf, "\n");
                    }
                }
            }
        }
        else if (DRV_IS_BIT_SET(flag, 0))
        {
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            if (DRV_E_NONE != drv_ioctl_bmp_api(lchip, entry_id+local_idx, ((uint64)oper_bmp<<32)|cmd, hw_buffer))
            {
                break;
            }
            if (0 != sal_memcmp(hw_buffer, sw_buffer, TABLE_ENTRY_SIZE(lchip, tbl_id)))
            {
                check_fail = TRUE;
                break;
            }
            else if ((p_drv_master[lchip]->dev_type < DRV_ARCTIC) ||
                (TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_DP && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PEER_DP))
            {
                continue;
            }
            else
            {
                oper_bmp = (oper_bmp & (~(3))) | 2;
                sw_buffer = drv_sdb_read(lchip, tbl_id, entry_id+local_idx, entry_size, oper_bmp);
                cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
                if (DRV_E_NONE != drv_ioctl_bmp_api(lchip, entry_id+local_idx, ((uint64)oper_bmp<<32)|cmd, hw_buffer))
                {
                    break;
                }
                DRV_SDB_IF_CONTINUE(0 == sal_memcmp(hw_buffer, sw_buffer, TABLE_ENTRY_SIZE(lchip, tbl_id)));
                check_fail = TRUE;
                break;
            }
                
        }
    }

    if (TRUE == check_fail)
    {
        if (p_tcam_db != NULL)
        {
            DRV_SDB_DUMP_FILE(pf, "  Table(%s) type(%d) lchip(%d) index(%u) check fail! \n", TABLE_NAME(lchip, tcam_tbl_id), TABLE_ENTRY_TYPE(lchip, tcam_tbl_id), lchip, entry_id/entry_num_each_idx);
        }
        else if (0 == _drv_sdb_check_table_field(lchip, tbl_id, hw_buffer, sw_buffer, pf))
        {
            mem_free(hw_buffer);
            return DRV_E_NONE;
        }
        else
        {
            DRV_SDB_DUMP_FILE(pf, "  Table(%s) type(%d) lchip(%d) index(%u) check fail! \n", TABLE_NAME(lchip, tbl_id), TABLE_ENTRY_TYPE(lchip, tbl_id), lchip, entry_id);
        }
        DRV_SDB_BUFFER_DUMP("hw_buffer: ", hw_buffer, TABLE_ENTRY_SIZE(lchip, tbl_id));
        DRV_SDB_BUFFER_DUMP("sw_buffer: ", sw_buffer, TABLE_ENTRY_SIZE(lchip, tbl_id));
        if (DRV_IS_BIT_SET(flag, 1))
        {
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            sal_memcpy(hw_buffer, sw_buffer, TABLE_ENTRY_SIZE(lchip, tbl_id));
            drv_ioctl_api(lchip, entry_id+local_idx, ((uint64)oper_bmp<<32)|cmd, hw_buffer);
        }
    }
    /*
    else
    DRV_SDB_DUMP_FILE(pf, "  Table(%s) check pass!\n", TABLE_NAME(lchip, tbl_id));
    */
    mem_free(hw_buffer);

    return DRV_E_NONE;
}

int32
_drv_sdb_check_static_table(uint8 lchip, uint8 flag, uint8 tcam_mem, sal_file_t pf)
{
    uint32 tbl_id = 0;

    for (tbl_id=0; tbl_id<MaxTblId_t; tbl_id++)
    {
        DRV_SDB_IF_CONTINUE(DRV_FTM_TABLE_STATIC != _drv_sdb_get_tbl_type(lchip, tbl_id) ||
                            tcam_mem == DRV_TBL_TCAM_MEM(tbl_id) ||
                            0 == DRV_SDB_READ(tbl_id));
        DRV_SDB_IF_CONTINUE(TABLE_INFO(lchip, tbl_id).field_num == 0 || !DRV_SDB_MODE_VALID(tbl_id) || 0 == DRV_SDB_ADDR_BASE(tbl_id));
        DRV_IF_ERROR_RETURN(_drv_sdb_check_per_table(lchip, tbl_id, flag, pf));
    }
    return DRV_E_NONE;
}

uint32
_drv_sdb_get_table_by_name(uint8 lchip, char* tbl_name)
{
    uint32 tbl_id = 0;
    uint16 usr_tbl_size = sal_strlen(tbl_name);
    uint16 drv_tbl_size = 0;
    do {
        DRV_SDB_IF_CONTINUE(TABLE_NAME(lchip, tbl_id) == NULL);
        drv_tbl_size = sal_strlen(TABLE_NAME(lchip, tbl_id));
        if (drv_tbl_size == usr_tbl_size && 0 == sal_strncasecmp(TABLE_NAME(lchip, tbl_id), tbl_name, usr_tbl_size))
        {
            break;
        }
    }while(++tbl_id < MaxTblId_t);
    return tbl_id;
}

/*
  type -  0 - dump static table
  type -  1 - dump dynamic table by mem_id(tbl_id)
  type -  2 - dump tcam key
  type -  3 - dump specified table
*/
int32
drv_sdb_dump(uint8 lchip, uint8 type, uint32 table_id, char* p_file)
{
    int32  ret = 0;
    uint32 mem_id = 0;
    uint8  cmp_result = 0;
    sal_file_t  pf = NULL;
    uint8 flag = 1<<2;

    DRV_SDB_INIT_CHECK(lchip);
    if (!g_sdb_master[lchip] || (!p_file && 3 != type))
    {
        return DRV_E_NONE;
    }
    if (p_file)
    {
        pf = sal_fopen(p_file, "w");
        if (!pf)
        {
            return DRV_E_FILE_OPEN_FAILED;
        }
    }

    switch(type)
    {
    case 0:
        ret = _drv_sdb_check_static_table(lchip, flag, 1, pf);
        break;
    case 1:
        for (mem_id = 0; !ret && mem_id<DRV_FTM_MAX_ID; mem_id++)
        {
            if (DRV_FTM_MEM_DYNAMIC != _drv_sdb_get_ram_type(lchip, mem_id, FALSE))
            {
                continue;
            }
            
            ret = drv_sdb_check_per_ram(lchip, mem_id, flag, &cmp_result, pf);
        }
        break;
    case 2:
        for (mem_id = 0; !ret && mem_id<DRV_FTM_MAX_ID; mem_id++)
        {
            if (DRV_FTM_MEM_DYNAMIC == _drv_sdb_get_ram_type(lchip, mem_id, FALSE))
            {
                continue;
            }
                    
            ret = drv_sdb_check_per_ram(lchip, mem_id, flag, &cmp_result, pf);
        }
        break;
    case 3:
        if(DRV_SDB_ADDR_BASE(table_id) && DRV_SDB_MODE_VALID(table_id) && DRV_SDB_READ(table_id))
        {
            ret = _drv_sdb_check_per_table(lchip, table_id, flag, pf);
        }
        break;
    default:
        ret = _drv_sdb_check_static_table(lchip, 0, 1, pf);
        for (mem_id = 0; !ret && mem_id<DRV_FTM_MAX_ID; mem_id++)
        {
            ret = drv_sdb_check_per_ram(lchip, mem_id, flag, &cmp_result, pf);
        }
        break;
    }
    if (p_file)
    {
        sal_fclose(pf);
    }
    return ret;
}

/*
  type -  0 - static table check
  type -  1 - dynamic table check by mem_id(tbl_id)
  type -  2 - tcam key check
  type -  3 - per table info
  flag 
    bit 0  tbl check
    bit 1  tbl recover from software
    bit 2  tbl dump
*/
int32
drv_sdb_check(uint8 lchip, uint8 type, uint8 flag, uint32 table_id, char* file)
{
    int32  ret = 0;
    uint32 mem_id = 0;
    uint8  read_tbl_from_hw = 0;
    uint8  cmp_result = 0;
    sal_file_t  pf = NULL;

    DRV_SDB_INIT_CHECK(lchip);
    if (!g_sdb_master[lchip])
    {
        return DRV_E_NONE;
    }
#if (1 == SDK_WORK_PLATFORM)
    if (0 != type)  /* uml only support static tbl check */
    {
        return DRV_E_NONE;
    }
#endif
    if (file)
    {
        pf = sal_fopen(file, "w");
        if (!pf)
        {
            return DRV_E_FILE_OPEN_FAILED;
        }
    }
    read_tbl_from_hw = DRV_SDB_DB(lchip)->read_tbl_from_hw;
    DRV_SDB_DB(lchip)->read_tbl_from_hw = 1;
    flag = (flag? (1<<1 | 1<<0): (1<<0));
    switch(type)
    {
    case 0: /* all static table check */
        ret = _drv_sdb_check_static_table(lchip, flag, 1, pf);
        break;
    case 1:
        for (mem_id = 0; !ret && mem_id<DRV_FTM_MAX_ID; mem_id++)
        {
            if (DRV_FTM_MEM_DYNAMIC != _drv_sdb_get_ram_type(lchip, mem_id, FALSE))
            {
                continue;
            }

            ret = drv_sdb_check_per_ram(lchip, mem_id, flag, &cmp_result, pf);
        }
        break;
    case 2:
        for (mem_id = 0; !ret && mem_id<DRV_FTM_MAX_ID; mem_id++)
        {
            if (DRV_FTM_MEM_DYNAMIC == _drv_sdb_get_ram_type(lchip, mem_id, FALSE))
            {
                continue;
            }

            ret = drv_sdb_check_per_ram(lchip, mem_id, flag, &cmp_result, pf);
        }
        break;
    case 3:
        if(DRV_SDB_ADDR_BASE(table_id) && DRV_SDB_MODE_VALID(table_id) && DRV_SDB_READ(table_id))
        {
            ret = _drv_sdb_check_per_table(lchip, table_id, flag, pf);
        }
        break;
    default:
        ret = _drv_sdb_check_static_table(lchip, flag, 1, pf);
        for (mem_id = 0; !ret && mem_id<DRV_FTM_MAX_ID; mem_id++)
        {
            ret = drv_sdb_check_per_ram(lchip, mem_id, flag, &cmp_result, pf);
        }
        break;
    }

    DRV_SDB_DB(lchip)->read_tbl_from_hw = read_tbl_from_hw;
    if (file)
    {
        sal_fclose(pf);
    }
    return ret;
}

int32
drv_sdb_set_table_mode(uint8 lchip, uint32 tbl_id, uint8 mode)
{
    DRV_INIT_CHECK(lchip);
    DRV_SDB_MODE(tbl_id) = mode;
    return DRV_E_NONE;
}

STATIC INLINE void
drv_sdb_get_table_addr(uint8 lchip, uint32 tbl_id, uintptr* addrs)
{
    addrs[0] = (uintptr)drv_sdb_type_str[DRV_SDB_MODE(tbl_id)];
#if (SDB_TIMESTAMP == SDB_MODE)
    addrs[1] = (uintptr)DRV_SDB_ADDR_BASE(tbl_id);
    if (0 != TABLE_INFO(lchip, tbl_id).field_num && DRV_SDB_MODE_VALID(tbl_id) && 0 != DRV_SDB_ADDR_BASE(tbl_id))
    {
        addrs[2] = (uintptr)(((drv_sdb_ts_hdr_t*)(DRV_SDB_ADDR_BASE(tbl_id) - sizeof(drv_sdb_ts_hdr_t)))->ent_ts_offset);
    }
    else
    {
        addrs[2] = 0;
    }
#else
    addrs[1] = (uintptr)DRV_SDB_ADDR_BASE(tbl_id);
    addrs[2] = 0;
#endif
}

/*
  type -  0 - only sdb macro info
  type -  1 - overview
  type -  2 - static table info
  type -  3 - dynamic table info
  type -  4 - tcam table info
  type -  5 - per table info
*/

int32
drv_sdb_show_status(uint8 lchip, uint8 type, char* table_name)
{
#define SDB_TBL_NAME_FMT    "%-40s"
    uint32 tbl_id = 0;
    uint32 act_size = 0;
    uintptr addrs[3] = {0};
    char* sdb_mode_str[] = {
        "Disable", "Optimize I/O", "All table enable SDB"
    };
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    uint8  ecc_recover_en = 0;
    uint8 pp_base =drv_vchip_get_pp_base(lchip);
    uint8 pp_num = drv_vchip_get_pp_num(lchip);
    uint8 index = 0;

    DRV_SDB_INIT_CHECK(lchip);
    drv_ser_get_master_info(lchip, &ecc_recover_en);
#if (SDB_TIMESTAMP == SDB_MODE)
    DRV_SDB_DUMP("%-20s : %d\n", "Timestamp enable", 1);
#else
    DRV_SDB_DUMP("%-20s : %d\n", "Timestamp enable", 0);
#endif
#if (SDB_MEM_MODEL == SDB_MODE)
    DRV_SDB_DUMP("%-20s : %d\n", "Memory mode", 1);
#else
    DRV_SDB_DUMP("%-20s : %d\n", "Memory mode", 0);
#endif

    DRV_SDB_DUMP("%-20s : %d\n", "SDB enable", p_sdb->sdb_en);
    DRV_SDB_DUMP("%-20s : %d\n", "ECC recover en", ecc_recover_en);
    if (p_drv_master[lchip]->sdb_type != SDB_DIS && p_drv_master[lchip]->sdb_type <= SDB_ALL)
    {
        DRV_SDB_DUMP("%-20s : %s\n", "Work mode", sdb_mode_str[p_drv_master[lchip]->sdb_type]);
    }

    if (1 == type)  /* overall info */
    {
        DRV_SDB_DUMP("%-20s : %-5u kB\n", "Reserved memory size", (g_sdb_master[pp_base]->mem_size+(1<<10)-1)>>10);
        for(index = pp_base; index < pp_base + pp_num; index++)
        {
            act_size += drv_sdb_calc_tbl_size(index, 2);
        }
        DRV_SDB_DUMP("%-20s : %-5u kB\n", "Actual memory size", (act_size+(1<<10)-1)>>10);

        if (p_sdb->sdb_en)
        {
            DRV_SDB_DUMP("%-20s : %u\n",     "PMEM enable",       p_sdb->pmem_en);
            DRV_SDB_DUMP("%-20s : %p\n",   "Memory address",      (void *)p_sdb->mem_addr);
            DRV_SDB_DUMP("%-20s : %-5u kB\n", "Static table size",   p_sdb->catch_mem_static_size>>10);
            DRV_SDB_DUMP("%-20s : %-5u kB\n", "Dynamic table size",  p_sdb->catch_mem_dynamic_size>>10);
            DRV_SDB_DUMP("%-20s : %u\n",     "HW reset status", p_sdb->hw_reset_status);
            DRV_SDB_DUMP("%-20s : %u\n",     "Read from hardware",  p_sdb->read_tbl_from_hw);
        }
    }
    else
    {
        DRV_SDB_DUMP("\n"SDB_TBL_NAME_FMT"  TABLE_ID  SDB_TYPE  DATA_MEM_ADDR  DATA_MEM_SIZE\n", "TABLE_NAME");
        DRV_SDB_DUMP("-----------------------------------------------------------------------------------------------\n");
        for (tbl_id=0; tbl_id<MaxTblId_t; tbl_id++)
        {
            DRV_SDB_IF_CONTINUE(TABLE_INFO(lchip, tbl_id).field_num == 0 ||
                                !DRV_SDB_MODE_VALID(tbl_id) ||
                                0 == DRV_SDB_ADDR_BASE(tbl_id));
            switch(type)
            {
            case 2:
                DRV_SDB_IF_CONTINUE(DRV_TBL_TCAM_MEM(tbl_id) ||
                                DRV_FTM_TABLE_STATIC != _drv_sdb_get_tbl_type(lchip, tbl_id));
                break;
            case 3:
                DRV_SDB_IF_CONTINUE(DRV_FTM_TABLE_STATIC == _drv_sdb_get_tbl_type(lchip, tbl_id));
                break;
            case 4:
                DRV_SDB_IF_CONTINUE(!DRV_TBL_TCAM_MEM(tbl_id));
                break;
            default:
                break;
            }
            /* addrs[0] sdb type addrs[1] tbl base addrs[2] entry ts info */
            drv_sdb_get_table_addr(lchip, tbl_id, addrs);
            DRV_SDB_DUMP(SDB_TBL_NAME_FMT"  %-8u  %-8s  %-11p  %-18p\n",
                         TABLE_NAME(lchip, tbl_id), tbl_id, (char*)addrs[0], (void *)addrs[1], (void *)addrs[2]);
        }
        DRV_SDB_DUMP("\n");
    }

    return DRV_E_NONE;
}

#if (SDB_TIMESTAMP == SDB_MODE)
STATIC int32
_drv_sdb_show_change_table(uint8 lchip, uint32 tbl_id, uint32 start_time, uint32 end_time)
{
    drv_sdb_ts_hdr_t* p_ts_hdr = NULL;
    char* p_time_str = NULL;
    uint32* p_entry_ts = NULL;
    sal_time_t tmp_ts = 0;
    uint32 entry_idx = 0;

    p_ts_hdr = (drv_sdb_ts_hdr_t*)(DRV_SDB_ADDR_BASE(tbl_id) - sizeof(drv_sdb_ts_hdr_t));
    tmp_ts = p_ts_hdr->tbl_ts;
    if (start_time < tmp_ts && tmp_ts <= end_time)
    {
        p_time_str = sal_ctime((sal_time_t*)&tmp_ts); 
        if (p_time_str) DRV_DUMP_INFO("%-40s%-10u%-14s%s\n",
                        TABLE_NAME(lchip, tbl_id), tbl_id, "-- ", p_time_str);
        for (entry_idx=0; entry_idx<TABLE_MAX_INDEX(lchip, tbl_id); entry_idx++)
        {
            p_entry_ts = (uint32*)DRV_SDB_ENT_TS_PTR(tbl_id, p_ts_hdr, entry_idx);
            tmp_ts = *p_entry_ts;
            DRV_SDB_IF_CONTINUE(0 == tmp_ts || tmp_ts < start_time || tmp_ts > end_time);
            p_time_str = sal_ctime((sal_time_t*)&tmp_ts);
            if (p_time_str) DRV_DUMP_INFO("%-40s%-10s%-14u%s\n",
                            "", "dp 0", entry_idx, p_time_str);
        }
        if ((p_drv_master[lchip]->dev_type >= DRV_ARCTIC) && (DRV_FEATURE_MODE_PER_DP == DRV_TBL_FEA_MOD(tbl_id) || DRV_FEATURE_MODE_PEER_DP == DRV_TBL_FEA_MOD(tbl_id)))
        {
            for (entry_idx=0; entry_idx<TABLE_MAX_INDEX(lchip, tbl_id); entry_idx++)
            {
                p_entry_ts = (uint32*)DRV_SDB_ENT_TS_PTR(tbl_id, p_ts_hdr, entry_idx) + DRV_SDB_TS_SIZE * 
                    TABLE_MAX_INDEX(lchip, tbl_id) + p_ts_hdr->ent_ts_offset;
                tmp_ts = *p_entry_ts;
                DRV_SDB_IF_CONTINUE(0 == tmp_ts || tmp_ts < start_time || tmp_ts > end_time);
                p_time_str = sal_ctime((sal_time_t*)&tmp_ts);
                if (p_time_str) DRV_DUMP_INFO("%-40s%-10s%-14u%s\n",
                                "", "dp 1", entry_idx, p_time_str);
            }
        }
    }

    return DRV_E_NONE;
}
#endif

int32
drv_sdb_show_changed_table(uint8 lchip, char* tbl_name, uint32 start_time, uint32 end_time)
{
#if (SDB_TIMESTAMP == SDB_MODE)
    uint32 tbl_id = 0;

    DRV_SDB_INIT_CHECK(lchip);
    if (!end_time)
    {
        end_time = (uint32)sal_time(NULL);
    }
    if (start_time > end_time)
    {
        DRV_DUMP_INFO("%%  end time(%u) is earlier than start time(%u)!\n", end_time, start_time);
        return DRV_E_NONE;
    }

    DRV_DUMP_INFO("%-40s%-10s%-14s%-22s\n", "TABLE NAME", "TABLE ID", "ENTRY INDEX", "TIMESTAMP");
    DRV_DUMP_INFO("----------------------------------------------------------------------------\n");
    if (sal_strlen(tbl_name) != 0)   /*per table*/
    {
        for (tbl_id=0; tbl_id<MaxTblId_t; tbl_id++)  /*find tbl*/
        {
            DRV_SDB_IF_CONTINUE(TABLE_INFO(lchip, tbl_id).field_num == 0 || !DRV_SDB_MODE_VALID(tbl_id) || DRV_SDB_ADDR_BASE(tbl_id) == 0);
            DRV_SDB_IF_CONTINUE(sal_strlen(tbl_name)!=sal_strlen(TABLE_NAME(lchip, tbl_id)) || sal_strcasecmp(tbl_name, TABLE_NAME(lchip, tbl_id)));
            _drv_sdb_show_change_table(lchip, tbl_id, start_time, end_time);
            break;
        }
    }
    else    /*all table*/
    {
        for (tbl_id=0; tbl_id<MaxTblId_t; tbl_id++)
        {
            DRV_SDB_IF_CONTINUE(TABLE_INFO(lchip, tbl_id).field_num == 0 || !DRV_SDB_MODE_VALID(tbl_id) || DRV_SDB_ADDR_BASE(tbl_id) == 0);
            _drv_sdb_show_change_table(lchip, tbl_id, start_time, end_time);
        }
    }
#endif
    return DRV_E_NONE;
}

int32
drv_sdb_store(uint8 lchip, tbls_id_t tbl_id, uint32 entry_idx, void* p_data, uint32 entry_size, uint8 dp_id)
{
#if (SDB_TIMESTAMP == SDB_MODE)
    uint32*              p_entry_ts = NULL;
    drv_sdb_ts_hdr_t*    p_ts_hdr = NULL;
    drv_sdb_mem_hdr_t*   p_mem_hdr = NULL;
    uint32 tv_sec[2] = {0};
#endif
    drv_sdb_t* p_sdb = NULL;
    uint32 tbl_max_size = 0;
    uint32 real_index = entry_idx & 0x7fffffff;
    uint8 mask_write = entry_idx>>31 & 0x1;
    uint32 real_size = entry_size>>mask_write;

    p_sdb = (drv_sdb_t*)(g_sdb_master[lchip]);

    if (NULL == p_sdb || 0 == p_sdb->sdb_en || DRV_SDB_ADDR_BASE(tbl_id) == 0)
    {
        return DRV_E_NONE;
    }
    if (p_drv_master[lchip]->dev_type >= DRV_ARCTIC && dp_id)
    {
#if (SDB_TIMESTAMP == SDB_MODE)
        tbl_max_size = TABLE_MAX_INDEX(lchip, tbl_id) * real_size + (TABLE_MAX_INDEX(lchip, tbl_id) * DRV_SDB_TS_SIZE);
#else
        tbl_max_size = TABLE_MAX_INDEX(lchip, tbl_id) * real_size;
#endif
    }

#if (SDB_TIMESTAMP == SDB_MODE)
    p_ts_hdr = (drv_sdb_ts_hdr_t*)(DRV_SDB_ADDR_BASE(tbl_id) - sizeof(drv_sdb_ts_hdr_t));
    if (mask_write && (0 == SDK_WORK_PLATFORM))
    {
        uint32* p_mem = NULL;
        uint8 word = 0;
        uint8 num = entry_size>>3;

        if (DRV_TSINGMA == p_drv_master[lchip]->dev_type && 48 == real_size)
        {
            real_index >>= 2;
        }
        p_mem = (uint32*)(DRV_SDB_ADDR_BASE(tbl_id) + real_size * real_index + tbl_max_size);
        for (word = 0; word < num; word++)
        {
            if (0 != ((uint32*)p_data)[word<<1])
            {
                p_mem[word] &= ~((uint32*)p_data)[word<<1];
                p_mem[word] |= (((uint32*)p_data)[(word<<1)+1]&((uint32*)p_data)[word<<1]);
            }
        }
    }
    else
    {
        sal_memcpy((uint8*)DRV_SDB_ADDR_BASE(tbl_id) + real_size * real_index + tbl_max_size, p_data, TABLE_ENTRY_SIZE(lchip, tbl_id));
    }
    p_mem_hdr = (drv_sdb_mem_hdr_t*)p_sdb->mem_addr;

    p_entry_ts = (uint32*)(DRV_SDB_ENT_TS_PTR(tbl_id, p_ts_hdr, real_index) + tbl_max_size);
    tv_sec[1] = (uint32)sal_time(NULL);
    p_ts_hdr->tbl_ts = tv_sec[p_mem_hdr->init_done];
    *p_entry_ts = tv_sec[p_mem_hdr->init_done];
#else
    if (mask_write && (0 == SDK_WORK_PLATFORM))
    {
        uint32* p_mem = NULL;
        uint8 word = 0;
        uint8 num = entry_size>>3;

        if (DRV_TSINGMA == p_drv_master[lchip]->dev_type && 48 == real_size)
        {
            real_index >>= 2;
        }
        p_mem = (uint32*)(DRV_SDB_ADDR_BASE(tbl_id) + real_size * real_index + tbl_max_size);
        for (word = 0; word < num; word++)
        {
            if (0 != ((uint32*)p_data)[word<<1])
            {
                p_mem[word] &= ~((uint32*)p_data)[word<<1];
                p_mem[word] |= (((uint32*)p_data)[(word<<1)+1]&((uint32*)p_data)[word<<1]);
            }
        }
    }
    else
    {
        sal_memcpy((uint8*)DRV_SDB_ADDR_BASE(tbl_id) + real_size * real_index + tbl_max_size, p_data, TABLE_ENTRY_SIZE(lchip, tbl_id));
    }
#endif
    return DRV_E_NONE;
}

int32
drv_sdb_write(uint8 lchip, tbls_id_t tbl_id, uint32 entry_idx, void* p_data, uint32 entry_size, uint8 oper_bmp)
{
    uint8 pp_base = drv_vchip_get_pp_base(lchip);
    uint8 pp_id = 0;
    uint8 dp_id = 0;
    uint8 pp_min = 0;
    uint8 pp_max = 0;

    if ((p_drv_master[lchip]->dev_type < DRV_ARCTIC) ||
        (DRV_TBL_FEA_MOD(tbl_id) == DRV_FEATURE_MODE_PER_CORE && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_CORE))
    {
        drv_sdb_store(pp_base, tbl_id, entry_idx, p_data, entry_size, 0);
        return DRV_E_NONE;
    }

    switch(DRV_TBL_FEA_MOD(tbl_id))
    {
    case MEM_TYPE_PER_CORE:
        if (DRV_IS_BIT_SET(oper_bmp, 7))    /*core 1*/
        {
            drv_sdb_store(pp_base+p_drv_master[lchip]->core_pp_num, tbl_id, entry_idx, p_data, entry_size, 0);
        }
        if (DRV_IS_BIT_SET(oper_bmp, 6))    /*core 0*/
        {
            drv_sdb_store(pp_base, tbl_id, entry_idx, p_data, entry_size, 0);
        }
        break;
    case MEM_TYPE_PER_PP:
    case MEM_TYPE_PEER_PP:
        if (DRV_IS_BIT_SET(oper_bmp, 7))    /*core 1*/
        {
            for (pp_id=0; pp_id<p_drv_master[lchip]->core_pp_num; pp_id++)
            {
                if (!DRV_IS_BIT_SET(oper_bmp, pp_id+2)) { continue; }
                drv_sdb_store(pp_base+p_drv_master[lchip]->core_pp_num+pp_id, tbl_id, entry_idx, p_data, entry_size, 0);
            }
        }
        if (DRV_IS_BIT_SET(oper_bmp, 6))    /*core 0*/
        {
            for (pp_id=0; pp_id<p_drv_master[lchip]->core_pp_num; pp_id++)
            {
                if (!DRV_IS_BIT_SET(oper_bmp, pp_id+2)) { continue; }
                drv_sdb_store(pp_base+pp_id, tbl_id, entry_idx, p_data, entry_size, 0);
            }
        }
        break;
    case MEM_TYPE_PER_DP:
    case MEM_TYPE_PEER_DP:
        pp_min = ((DRV_IS_BIT_SET(oper_bmp, 7) && DRV_IS_BIT_SET(oper_bmp, 6))? 0: (DRV_IS_BIT_SET(oper_bmp, 7)? 4: 0));
        pp_max = ((DRV_IS_BIT_SET(oper_bmp, 7) && DRV_IS_BIT_SET(oper_bmp, 6))? 8: (DRV_IS_BIT_SET(oper_bmp, 7)? 8: 4));

        for (pp_id=pp_min; pp_id<pp_max; pp_id++)
        {
            if (!DRV_IS_BIT_SET(oper_bmp, (pp_id % p_drv_master[lchip]->core_pp_num) + 2)) { continue; }
            for (dp_id = 0; dp_id < 2; dp_id++)
            {
                if (!DRV_IS_BIT_SET(oper_bmp, dp_id)) { continue; }
                drv_sdb_store(pp_base+pp_id, tbl_id, entry_idx, p_data, entry_size, dp_id);
            }
        }
        break;
    default:
        DRV_DBG_INFO("[SDB] tbl-name:%s is not support!\n", TABLE_NAME(lchip, tbl_id));
        return DRV_E_NONE;
    }
    return DRV_E_NONE;
}

int32
_drv_sdb_write_aps_oam_mask(uint8 lchip)
{
    uint32 cmd = 0;
    drv_ds_t  ds;

    sal_memset(ds, 0, sizeof(drv_ds_t));
    if ((p_drv_master[lchip]->dev_type == DRV_DUET2))
    {
        cmd = DRV_IOW(OamDsMpDataMask_t, DRV_ENTRY_FLAG);
        DRV_IF_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, ds));
        cmd = DRV_IOW(DsApsBridgeMask_t, DRV_ENTRY_FLAG);
        DRV_IF_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, ds));
    }
    else if ((p_drv_master[lchip]->dev_type == DRV_TSINGMA))
    {
        cmd = DRV_IOW(OamDsMpDataMask_t, DRV_ENTRY_FLAG);
        DRV_IF_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, ds));
        cmd = DRV_IOW(MetFifoDsApsMask_t, DRV_ENTRY_FLAG);
        DRV_IF_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    }
    else
    {
        cmd = DRV_IOW(DsMpMask_t, DRV_ENTRY_FLAG);
        DRV_IF_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, ds));
        cmd = DRV_IOW(DsApsBridgeMask_t, DRV_ENTRY_FLAG);
        DRV_IF_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    }
    return 0;
}
#if 0
#define PRINT_USED_TIME(str, tv2, tv1) \
    do {\
    if (tv2.tv_usec >= tv1.tv_usec)\
    {\
        sal_printf("%s USED  TIME:[%10u s:%3u us]\n", str, tv2.tv_sec - tv1.tv_sec, (tv2.tv_usec - tv1.tv_usec));\
    }\
    else\
    {\
        sal_printf("%s USED  TIME:[%10u s:%3u us]\n", str, tv2.tv_sec - tv1.tv_sec - 1, (tv2.tv_usec + 1000000 - tv1.tv_usec));\
    }\
    }while(0)
#endif
int32
drv_sdb_set_hw_reset_en(uint8 lchip, uint8 enable)
{
    uint32 i      = 0;
    int32 ret = 0;
    uint32 field_val = 0;
    uint32 cmd = 0;
    uint32 eunit_hw_reset = 0;
    drv_sdb_t* p_sdb = NULL;

    p_sdb = (drv_sdb_t*)(g_sdb_master[lchip]);
    if ((NULL == p_sdb) || (0 == enable) || (p_drv_master[lchip] && SDB_ALL != p_drv_master[lchip]->sdb_type))
    {
        return DRV_E_NOT_INIT;
    }
    
    /* reset eunit before hw reset */
    eunit_hw_reset = 1;
    if(p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_EUNIT])
    {
        DRV_IF_ERROR_RETURN(p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_EUNIT](lchip, (void*)&eunit_hw_reset));
    }

    DRV_IF_ERROR_GOTO(_drv_sdb_reset_register(lchip, 0), ret, recover_eunit);
    /*Disable all dma channel except knet channel, before reset core*/
    if(p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_DMA_CLEAR])
    {
        DRV_IF_ERROR_GOTO(p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_DMA_CLEAR](lchip, NULL), ret, recover_eunit);
    }
    p_sdb->hw_reset_status = 1;
    DRV_IF_ERROR_GOTO(drv_sdb_set_stop_store(lchip, TRUE), ret, recover_eunit);

    sal_task_sleep(10);
    field_val = 1;
    cmd = DRV_IOW(SupMiscCfg_t, SupMiscCfg_softResetCore_f);
    DRV_IF_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val), ret, recover_eunit);

    field_val = 0;
    cmd = DRV_IOW(SupMiscCfg_t, SupMiscCfg_softResetCore_f);
    DRV_IF_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val), ret, recover_eunit);

    /*module special process*/
    for (i = 0; i< DRV_SER_HW_RESET_CB_TYPE_NUM; i++)
    {
        DRV_SDB_IF_CONTINUE(NULL == p_sdb->reset_hw_cb[i]);
        DRV_SDB_IF_CONTINUE((i == DRV_SER_HW_RESET_CB_TYPE_EUNIT) || (i == DRV_SER_HW_RESET_CB_TYPE_FDB) || (i == DRV_SER_HW_RESET_CB_TYPE_MAC) || (i == DRV_SER_HW_RESET_CB_TYPE_DMA_CLEAR)|| (i == DRV_SER_HW_RESET_CB_TYPE_PTP));    /*reset at end*/
        DRV_IF_ERROR_GOTO(p_sdb->reset_hw_cb[i](lchip, NULL), ret, recover_eunit);
    }
    p_sdb->hw_reset_status  = 0;
    /*DRV_DBG_INFO("\n[SDB]Start chip tbl recover \n");*/
    DRV_IF_ERROR_GOTO(_drv_sdb_write_aps_oam_mask(lchip), ret, recover_eunit);
    /*static tbl recover: based on tbl_id*/
    DRV_IF_ERROR_GOTO(_drv_sdb_reset_static(lchip, enable), ret, recover_eunit);    
    DRV_IF_ERROR_GOTO(_drv_sdb_reset_dynamic(lchip, enable), ret, recover_eunit);

    DRV_IF_ERROR_GOTO(drv_sdb_set_stop_store(lchip, FALSE), ret, recover_eunit);
    DRV_IF_ERROR_GOTO(_drv_sdb_reset_register(lchip, 1), ret, recover_eunit);

    if (p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_FDB])
    {
        DRV_IF_ERROR_GOTO(p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_FDB](lchip, NULL), ret, recover_eunit);
    }
    
    if (p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_MAC])
    {
        DRV_IF_ERROR_GOTO(p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_MAC](lchip, NULL), ret, recover_eunit);
    }

    if (p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_PTP])
    {
        DRV_IF_ERROR_GOTO(p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_PTP](lchip, NULL), ret, recover_eunit);
    }
recover_eunit:
    /* wakeup eunit after hw reset */
    eunit_hw_reset = 0;
    if(p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_EUNIT])
    {
        DRV_IF_ERROR_RETURN(p_sdb->reset_hw_cb[DRV_SER_HW_RESET_CB_TYPE_EUNIT](lchip, (void*)&eunit_hw_reset));
    }

    /*Since dma has been reinit, reset dma mem index and desc index map to default value*/
    p_sdb->dma_mem_idx = 0;
    sal_memset(p_sdb->desc_index_map, 0xFF, sizeof(p_sdb->desc_index_map));

    /*DRV_DBG_INFO("\n[DB]pass \n");*/
    return ret;
}
#if SDK_WORK_PLATFORM == 0

STATIC int32
_drv_sdb_restore_static(uint8 lchip, drv_sdb_t* p_sdb)
{
    uint8* p_bucket_data = NULL;
    uint32*  temp_dma_memory = NULL;
    uint32 tbl_id = 0;
    uint32 tbl_index = 0;
    uint32 start_data_addr = 0;
    uint32   copy_entry_num[DRV_SDB_DMA_BUCKET_NUM] = {0};
    uint32   last_tbl_id[DRV_SDB_DMA_BUCKET_NUM] = {0};
    uint32   last_tbl_index[DRV_SDB_DMA_BUCKET_NUM] = {0};
    uint32   last_entry_offset[DRV_SDB_DMA_BUCKET_NUM] = {0};
    uint32   last_entry_size[DRV_SDB_DMA_BUCKET_NUM] = {0};
    uint8    last_tbl_dp1[DRV_SDB_DMA_BUCKET_NUM] = {0};
    uint32   tmp_entry_index = 0;
    uint32    entry_offset = 0;
    uint32 loop_cnt;
    uint32 loop;
    uint32 once_entry_num;
    drv_dma_tbl_rw_t dma_cfg;
    uint32  entry_size;
    uint32  entry_num;
    uint8  mem_block_num;
    uint8  loop1;
    uint8  tcam_block_shift = 0;
    uint8 tcam_block_id = 0;
    uint8 tcam_mem_id_base = 0;
    uint8 tcam_step;
    uint8 dp_tbl = 0;
    uint8 oper_bmp = 0, base_lchip = drv_vchip_get_pp_base(lchip);
    uint32* p_data_buffer = NULL;
    drv_sdb_t* p_sdb_base = (drv_sdb_t*)(g_sdb_master[base_lchip]);

    /*0. restore all static table*/
    for (tbl_id = 0 ; tbl_id < MaxTblId_t; tbl_id ++)
    {
        DRV_SDB_IF_CONTINUE(!DRV_SDB_MODE_VALID(tbl_id));
        DRV_SDB_IF_CONTINUE(_drv_sdb_get_tbl_type(lchip, tbl_id) != DRV_FTM_TABLE_STATIC);
        DRV_SDB_IF_CONTINUE(NULL == p_sdb->static_tbl[tbl_id]);

        /*DRV_DBG_INFO("Restore table id [%u], max index [%u]\n", tbl_id, TABLE_MAX_INDEX(lchip, tbl_id));*/

        entry_num = TABLE_MAX_INDEX(lchip, tbl_id);
        entry_offset = TABLE_ENTRY_OFFSET(lchip, tbl_id);
        entry_size = TABLE_ENTRY_SIZE(lchip, tbl_id);
        dp_tbl = 0;

        if (DRV_TBL_FEA_MOD(tbl_id) == DRV_FEATURE_MODE_PER_CORE && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_CORE)
        {
            if (lchip != base_lchip)
            {
                continue;
            }
        }
        else if (TABLE_ENTRY_TYPE(lchip, tbl_id) == DRV_FEATURE_MODE_PER_CORE)
        {
            if ((lchip != base_lchip) && (lchip != base_lchip + p_drv_master[lchip]->core_pp_num))
            {
                continue;
            }
        }

        /*1. Since the address of multiple DP may not be consecutive,judge use dma or not*/
        if((TABLE_ENTRY_TYPE(lchip, tbl_id) != SLICE_Cascade) && \
            (TABLE_ADDR_NUM(lchip, tbl_id) <= 1) && \
            (entry_num >= 8) && \
            (p_sdb->dma_read_cb) && ((p_sdb->dma_wait_done_cb)))
        {
            uint16  tmp_dma_mem_idx;
            uint32  tmp_desc_cnt=0;
            loop1 = 0;
            mem_block_num = 1;
            tcam_block_shift = 0;
            tcam_step = 0;

            /*1.1 Flow tcam and lpm tcam address is not consecutive, split into multiple dma operation*/
            if (tbl_id == FlowTcamTcamMem_t)
            {
                tcam_block_shift = p_drv_master[lchip]->drv_io_tcam_db[DRV_IO_TCAM_TYPE_FLOW].blk_shift;
                mem_block_num = entry_num>>tcam_block_shift;
                tcam_mem_id_base = DRV_FTM_TCAM_KEY0;
                tcam_step = 1;
            }
            else if (tbl_id == LpmTcamTcamMem_t)
            {
                tcam_block_shift = p_drv_master[lchip]->drv_io_tcam_db[DRV_IO_TCAM_TYPE_LPM].blk_shift;
                mem_block_num = entry_num>>tcam_block_shift;
                tcam_mem_id_base = DRV_FTM_LPM_TCAM_KEY0;
                tcam_step = (p_drv_master[lchip]->dev_type >= DRV_TSINGMA_MX)? 2 :4;
            }
            else if ((p_drv_master[lchip]->dev_type >= DRV_ARCTIC) && (TABLE_ENTRY_TYPE(lchip, tbl_id) == DRV_FEATURE_MODE_PER_DP || TABLE_ENTRY_TYPE(lchip, tbl_id) == DRV_FEATURE_MODE_PEER_DP))
            {
                /*for DP & PEER DP table, need read dp0 & dp1*/
                mem_block_num = 2;
                dp_tbl = 1;
            }

            /*1.2 config dma_cfg, use dma read channel to restore static table sdb */
            dma_cfg.user_dma_mode = 2;
            dma_cfg.entry_len = entry_size;
            dma_cfg.entry_offset = entry_offset;
            do
            {
                tbl_index = 0;
                once_entry_num = entry_num;
                if(tcam_step)
                {
                    tbl_index = loop1*(1<<tcam_block_shift);
                    tcam_block_id = tbl_index >> tcam_block_shift;
                    once_entry_num = DRV_MEM_ENTRY_NUM(lchip, tcam_mem_id_base+tcam_block_id*tcam_step)*tcam_step;
                    entry_num = once_entry_num;
                }

                /*1.3. Judge whether a DMA operation can read one consecutive memory*/
                once_entry_num = (DRV_SDB_MAX_DMA_SIZE(lchip)/entry_offset > once_entry_num) ? once_entry_num : (DRV_SDB_MAX_DMA_SIZE(lchip)/entry_offset);
                loop_cnt = (entry_num+once_entry_num-1)/once_entry_num;

                loop = 0;
                do
                {
                    tmp_dma_mem_idx = p_sdb->dma_mem_idx;
                    temp_dma_memory = p_sdb_base->dma_mem_bucket[tmp_dma_mem_idx];
                    /*1.3.1 wait current dma bucket done, 0xFFFF means not used*/
                    if(DRV_SDB_DMA_INVALID_DESC_IDX != p_sdb->desc_index_map[tmp_dma_mem_idx])
                    {
                        DRV_IF_ERROR_RETURN(p_sdb->dma_wait_done_cb(lchip, 1, p_sdb->desc_index_map[tmp_dma_mem_idx]));
                        /* If, last done, copy from dma memory to sdb one by one*/
                        tmp_entry_index = 0;
                        do
                        {
                            p_bucket_data = p_sdb->static_tbl[last_tbl_id[tmp_dma_mem_idx]] + last_tbl_index[tmp_dma_mem_idx] * (DRV_TBL_TCAM_MEM(last_tbl_id[tmp_dma_mem_idx])? last_entry_offset[tmp_dma_mem_idx]: last_entry_size[tmp_dma_mem_idx]);
                            if (last_tbl_dp1[tmp_dma_mem_idx])
                            {
                                /*For Dp1 table, SDB Memory need add DP0 size*/
                                p_bucket_data = p_sdb->static_tbl[last_tbl_id[tmp_dma_mem_idx]] + (last_tbl_index[tmp_dma_mem_idx] + TABLE_MAX_INDEX(lchip, last_tbl_id[tmp_dma_mem_idx])) * last_entry_size[tmp_dma_mem_idx];
                            }
                            p_data_buffer = (uint32*)((uint8*)temp_dma_memory+tmp_entry_index*last_entry_offset[tmp_dma_mem_idx]);
                            /*tcam mem need translate xy to dm*/
                            if (DRV_TBL_TCAM_MEM(last_tbl_id[tmp_dma_mem_idx]))
                            {
                                DRV_SDB_TCAM_XY2DM(p_data_buffer, ((last_entry_size[tmp_dma_mem_idx] >> 3) << 2));
                            }
                            sal_memcpy(p_bucket_data, (uint8*)p_data_buffer, last_entry_size[tmp_dma_mem_idx]);
                            ++last_tbl_index[tmp_dma_mem_idx];
                        }while(++tmp_entry_index < copy_entry_num[tmp_dma_mem_idx]);
                    }

                    oper_bmp = (p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1] | p_drv_master[lchip]->pp_bmp[g_drv_chip[lchip].pp_id] | 1)&
                               (p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, tbl_id)]);
                    last_tbl_dp1[tmp_dma_mem_idx] = 0;
                    if (dp_tbl && loop1 == 1)
                    {
                        /*oper for dp1*/
                        oper_bmp = (oper_bmp & (~(3))) | 2;
                        last_tbl_dp1[tmp_dma_mem_idx] = 1;
                    }
                    dma_cfg.op_bmp = oper_bmp;
                    dma_cfg.buffer = temp_dma_memory;
                    copy_entry_num[tmp_dma_mem_idx] = (loop == loop_cnt-1) ? (entry_num-loop*once_entry_num) : once_entry_num;
                    /*1.3.2 get table hw addr to dma_cfg and read with dma*/
                    drv_usw_table_get_hw_addr(lchip, tbl_id, tbl_index, &start_data_addr,0);
                    dma_cfg.tbl_addr = start_data_addr;
                    dma_cfg.entry_num = copy_entry_num[tmp_dma_mem_idx];
                    /*DRV_DBG_INFO("Use DMA, entry_size %u, entry offset %u, tbl index %u, hw addr 0x%x\n", entry_size,entry_offset, tbl_index, start_data_addr);*/
                    DRV_IF_ERROR_RETURN(p_sdb->dma_read_cb(lchip, &dma_cfg));
                    
                    /*1.3.3 when 4 descs read to trigger dma to read table*/
                    if (0 == (++tmp_desc_cnt)%DRV_SDB_DMA_TRIGGER_DESC_NUM)
                    {
                        DRV_IF_ERROR_RETURN(p_sdb->dma_trigger_cb(lchip, tmp_desc_cnt));
                        tmp_desc_cnt = 0;
                    }

                    /*1.3.4 store current operation table info*/
                    last_tbl_id[tmp_dma_mem_idx] = tbl_id;
                    last_tbl_index[tmp_dma_mem_idx] = tbl_index;
                    last_entry_offset[tmp_dma_mem_idx] = entry_offset;
                    last_entry_size[tmp_dma_mem_idx] = entry_size;
                    tbl_index+=copy_entry_num[tmp_dma_mem_idx];
                    /*1.3.5 record the descriptor index returned by dma*/
                    p_sdb->desc_index_map[tmp_dma_mem_idx] = dma_cfg.desc_index;
                    p_sdb->dma_mem_idx = ((tmp_dma_mem_idx + 1) == DRV_SDB_DMA_BUCKET_NUM) ? 0 : (tmp_dma_mem_idx+1);
                }while(++loop < loop_cnt);
            }while(++loop1 < mem_block_num);
            DRV_IF_ERROR_RETURN(p_sdb->dma_trigger_cb(lchip, tmp_desc_cnt));
        }
        /*2. restore static tbl with io, not use dma*/
        else
        {
            uint32 need_continue = 0;
            uint32 step = 0;
            uint32 tcam_mem_id = 0;
            uint32 tcam_local_index = 0;
            uint16 sdb_entry_offset = 0;
            uint8 burst_addr = 0;
            step = 1;

            /*2.1 Flow tcam and lpm tcam address is not consecutive, split into multiple dma operation*/
            if (tbl_id == FlowTcamTcamMem_t)
            {
                tcam_block_shift = p_drv_master[lchip]->drv_io_tcam_db[DRV_IO_TCAM_TYPE_FLOW].blk_shift;
                tcam_mem_id = DRV_FTM_TCAM_KEY0;
                need_continue = 1;
            }
            else if (tbl_id == LpmTcamTcamMem_t)
            {
                tcam_block_shift = p_drv_master[lchip]->drv_io_tcam_db[DRV_IO_TCAM_TYPE_LPM].blk_shift;
                tcam_mem_id = DRV_FTM_LPM_TCAM_KEY0;
                step = DRV_FROM_TMM(lchip)? 2: 4;
                need_continue = 1;
            }

            /*2.2 use io read hw one index by one, store sdb db*/
            sdb_entry_offset = DRV_TBL_TCAM_MEM(tbl_id)? entry_offset: entry_size;
            burst_addr = !(TABLE_OP_TYPE(lchip, tbl_id)&Op_DisBurst) && p_drv_master[lchip]->burst_en;
            for (tbl_index = 0; tbl_index < entry_num; tbl_index++)
            {
                oper_bmp = (p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1] | p_drv_master[lchip]->pp_bmp[g_drv_chip[lchip].pp_id] | 1)&
                           (p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, tbl_id)]);
                if (need_continue)
                {
                    tcam_block_id = tbl_index >> tcam_block_shift;
                    tcam_local_index = tbl_index & ((1<<tcam_block_shift)-1);
                    DRV_SDB_IF_CONTINUE(tcam_local_index >= DRV_MEM_ENTRY_NUM(lchip, tcam_mem_id+tcam_block_id*step)*step);
                }
                p_bucket_data = p_sdb->static_tbl[tbl_id] + tbl_index * (sdb_entry_offset);
                drv_usw_table_get_hw_addr(lchip, tbl_id, tbl_index, &start_data_addr,0);
                start_data_addr += burst_addr;
                drv_usw_chip_read_sram_entry(lchip, ((uint64)oper_bmp<<32)|start_data_addr, (uint32*)p_bucket_data, entry_size);
                if (DRV_TBL_TCAM_MEM(tbl_id))
                {
                    DRV_SDB_TCAM_XY2DM(p_bucket_data, ((entry_size >> 3) << 2));
                }
                if ((p_drv_master[lchip]->dev_type < DRV_ARCTIC) || 
                    (TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_DP && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PEER_DP))
                {
                    continue;
                }

                /* DP 1 */
                oper_bmp = (oper_bmp & (~(3)))|2;
                p_bucket_data = p_sdb->static_tbl[tbl_id] + (tbl_index + TABLE_MAX_INDEX(lchip, tbl_id)) * (sdb_entry_offset);
                drv_usw_chip_read_sram_entry(lchip, ((uint64)oper_bmp<<32)|start_data_addr, (uint32*)p_bucket_data, entry_size);
            }
        }
    }

    /*3. static table some desc not done and not process, need process before restore dynamic mem*/
    for(loop_cnt=0; loop_cnt<DRV_SDB_DMA_BUCKET_NUM; loop_cnt++)
    {
        loop = (p_sdb->dma_mem_idx + loop_cnt)%DRV_SDB_DMA_BUCKET_NUM;
        if(DRV_SDB_DMA_INVALID_DESC_IDX != p_sdb->desc_index_map[loop])
        {
            DRV_IF_ERROR_RETURN(p_sdb->dma_wait_done_cb(lchip, 1, p_sdb->desc_index_map[loop]));
            temp_dma_memory = p_sdb_base->dma_mem_bucket[loop];
            tmp_entry_index = 0;
            do
            {
                p_bucket_data = p_sdb->static_tbl[last_tbl_id[loop]] + last_tbl_index[loop] * (DRV_TBL_TCAM_MEM(last_tbl_id[loop])? last_entry_offset[loop]: last_entry_size[loop]);
                if (last_tbl_dp1[loop])
                {
                    /*For Dp1 table, SDB Memory need add DP0 size*/
                    p_bucket_data = p_sdb->static_tbl[last_tbl_id[loop]] + (last_tbl_index[loop] + TABLE_MAX_INDEX(lchip, last_tbl_id[loop])) * last_entry_size[loop];
                }
                p_data_buffer = (uint32*)((uint8*)temp_dma_memory+tmp_entry_index*last_entry_offset[loop]);
                if (DRV_TBL_TCAM_MEM(last_tbl_id[loop]))
                {
                    DRV_SDB_TCAM_XY2DM(p_data_buffer, ((last_entry_size[loop] >> 3) << 2));
                }
                sal_memcpy(p_bucket_data, (uint8*)p_data_buffer, last_entry_size[loop]);
                ++last_tbl_index[loop];
            }while(++tmp_entry_index < copy_entry_num[loop]);
            p_sdb->desc_index_map[loop] = DRV_SDB_DMA_INVALID_DESC_IDX;
        }
    }

    return DRV_E_NONE;
}
STATIC int32
_drv_sdb_restore_per_ram_by_io(uint8 lchip, uint8 mem_id, uint8 oper_bmp)
{
    uint32   entry_id = 0;
    uint32   entry_num = 0;
    uint32   mem_size = 0, entry_size = 0;
    uint32*  hw_addr_array = &DRV_MEM_INFO(lchip, mem_id).addr_3w;
    uint8*   sw_addr = 0;
    uint32   entry_offset = 0;
    uint8    sram_type = 0;
    uint8    dp_id = (oper_bmp>>1)&0x1;
    drv_sdb_t* p_sdb = (drv_sdb_t*)(g_sdb_master[lchip]);
    uint8*   p_sw_buffer = NULL;
    uintptr hw_base_addr = 0;

    entry_size = DRV_MEM_ENTRY_SIZE(lchip, mem_id);
    if (NULL == p_sdb->dynamic_tbl[mem_id] || entry_size == 0)
    {
        return DRV_E_NONE;
    }
    DRV_IF_ERROR_RETURN(drv_usw_ftm_get_sram_type(lchip, mem_id, &sram_type));
    if (DRV_FROM_TMM(lchip) && DRV_FTM_SRAM_TBL_MPLS_HASH_KEY == sram_type)
    {
        hw_addr_array = &DRV_MEM_INFO(lchip, mem_id).addr_6w;
    }
    DRV_SDB_ENTRY_SIZE_ALINE(entry_size, entry_offset);
    drv_usw_get_memory_size(lchip, mem_id, &mem_size);
    entry_num = mem_size / entry_size;

    /*DRV_DBG_INFO("Mem[%u] reset...\n", mem_id);*/
    sw_addr = p_sdb->dynamic_tbl[mem_id] + (dp_id? mem_size<<2: 0);
    hw_base_addr = hw_addr_array[DRV_MEM_ADDR_SEL(lchip, mem_id)];
    do
    {
        p_sw_buffer = sw_addr + _drv_sdb_get_entry_offset(lchip, ((mem_id<<24) | sram_type), entry_id, entry_size, p_sdb);
        drv_usw_chip_read_sram_entry(lchip, ((uint64)oper_bmp<<32)|(hw_base_addr+entry_id*entry_offset), (uint32*)p_sw_buffer, entry_size);
    }while(++entry_id < entry_num);
    return DRV_E_NONE;
}

STATIC int32
_drv_sdb_restore_per_ram_by_dma(uint8 lchip, uint8 mem_id, uint8 oper_bmp)
{
    uint32*  hw_addr_array = &DRV_MEM_INFO(lchip, mem_id).addr_3w;
    drv_sdb_t* p_sdb = (drv_sdb_t*)(g_sdb_master[lchip]);
    drv_dma_tbl_rw_t dma_cfg;
    uint32*   temp_dma_memory = NULL;
    uint8*   p_sw_buffer = NULL;
    uint32   entry_offset = 0;
    uint32   loop_cnt = 0;
    uint32   loop = 0;
    uint32   once_entry_num = 0;
    int32    ret = 0;
    uint32   entry_id = 0;
    uint32   entry_num = 0;
    uint32   mem_size = 0, entry_size = 0;
    uint32   tmp_entry_index = 0;
    uint8    sram_type = 0;
    uint8    dp_id = (oper_bmp>>1)&0x1;
    uint32  copy_entry_num[DRV_SDB_DMA_BUCKET_NUM] = {0};
    uint8*   sw_addr = NULL;
    uintptr hw_base_addr = 0;
    uint32 tmp_desc_cnt = 0;
    drv_sdb_t* p_sdb_base = (drv_sdb_t*)(g_sdb_master[drv_vchip_get_pp_base(lchip)]);

    entry_size = DRV_MEM_ENTRY_SIZE(lchip, mem_id);
    if (NULL == p_sdb->dynamic_tbl[mem_id] || entry_size == 0)
    {
        return DRV_E_NONE;
    }

    drv_usw_get_memory_size(lchip, mem_id, &mem_size);
    entry_num = mem_size / entry_size;
    DRV_SDB_ENTRY_SIZE_ALINE(entry_size, entry_offset);

    /*1. Judge whether a DMA operation can write one consecutive memory*/
    once_entry_num = DRV_SDB_MAX_DMA_SIZE(lchip)/entry_offset;
    loop_cnt = (entry_num+once_entry_num-1)/once_entry_num;

    DRV_IF_ERROR_RETURN(drv_usw_ftm_get_sram_type(lchip, mem_id, &sram_type));
    if (DRV_FROM_TMM(lchip) && DRV_FTM_SRAM_TBL_MPLS_HASH_KEY == sram_type)
    {
        hw_addr_array = &DRV_MEM_INFO(lchip, mem_id).addr_6w;
    }
    sw_addr = p_sdb->dynamic_tbl[mem_id] + (dp_id? mem_size<<2: 0);
    hw_base_addr = hw_addr_array[DRV_MEM_ADDR_SEL(lchip, mem_id)];
    dma_cfg.user_dma_mode = 2;
    dma_cfg.entry_len = entry_size;
    dma_cfg.entry_offset = entry_offset;
    dma_cfg.op_bmp = oper_bmp;
    do
    {
        temp_dma_memory = p_sdb_base->dma_mem_bucket[p_sdb->dma_mem_idx];

        /*2. wait current dma bucket done*/
        if(DRV_SDB_DMA_INVALID_DESC_IDX != p_sdb->desc_index_map[p_sdb->dma_mem_idx])
        {
            DRV_IF_ERROR_RETURN(p_sdb->dma_wait_done_cb(lchip, 1, p_sdb->desc_index_map[p_sdb->dma_mem_idx]));

            /*3. copy from dma memory to sdb*/
            tmp_entry_index = 0;
            do
            {
                p_sw_buffer = sw_addr + _drv_sdb_get_entry_offset(lchip, ((mem_id<<24) | sram_type), entry_id, entry_size, p_sdb);
                sal_memcpy(p_sw_buffer, (uint8*)temp_dma_memory+tmp_entry_index*entry_offset, entry_size);
                ++entry_id;
            }while(++tmp_entry_index < copy_entry_num[p_sdb->dma_mem_idx]);
        }

        dma_cfg.buffer = temp_dma_memory;
        copy_entry_num[p_sdb->dma_mem_idx] = (loop == loop_cnt-1) ? (entry_num-loop*once_entry_num) : once_entry_num;

        dma_cfg.tbl_addr = (hw_base_addr+loop*DRV_SDB_MAX_DMA_SIZE(lchip));
        dma_cfg.entry_num = copy_entry_num[p_sdb->dma_mem_idx];

        /*sal_printf("dma_cfg.tbl_addr_hex:0x%10x dma_cfg.buffer:0x%10x,dma_cfg.entry_num:%10u,dma_cfg.entry_len:%10u \n", dma_cfg.tbl_addr,dma_cfg.buffer, dma_cfg.entry_num,dma_cfg.entry_len);*/
        DRV_IF_ERROR_GOTO(p_sdb->dma_read_cb(lchip, &dma_cfg), ret, error_rollback);
        /*3. when 4 descs read to trigger dma to read table*/
        if (0 == (++tmp_desc_cnt)%DRV_SDB_DMA_TRIGGER_DESC_NUM)
        {
            DRV_IF_ERROR_RETURN(p_sdb->dma_trigger_cb(lchip, tmp_desc_cnt));
            tmp_desc_cnt = 0;
        }
        /*4. record the descriptor index returned by dma*/
        p_sdb->desc_index_map[p_sdb->dma_mem_idx] = dma_cfg.desc_index;
        p_sdb->dma_mem_idx = ((p_sdb->dma_mem_idx + 1) == DRV_SDB_DMA_BUCKET_NUM) ? 0 : (p_sdb->dma_mem_idx+1);
    }while(++loop < loop_cnt);
    DRV_IF_ERROR_RETURN(p_sdb->dma_trigger_cb(lchip, tmp_desc_cnt));

    /*5. one mem some desc not done and not process, need process before restore next mem*/
    for(loop_cnt=0; loop_cnt<DRV_SDB_DMA_BUCKET_NUM; loop_cnt++)
    {
        loop = (p_sdb->dma_mem_idx + loop_cnt)%DRV_SDB_DMA_BUCKET_NUM;
        if(DRV_SDB_DMA_INVALID_DESC_IDX != p_sdb->desc_index_map[loop])
        {
            temp_dma_memory = p_sdb_base->dma_mem_bucket[loop];
            DRV_IF_ERROR_RETURN(p_sdb->dma_wait_done_cb(lchip, 1, p_sdb->desc_index_map[loop]));
            tmp_entry_index = 0;
            do
            {
                p_sw_buffer = sw_addr + _drv_sdb_get_entry_offset(lchip, ((mem_id<<24) | sram_type), entry_id, entry_size, p_sdb);
                sal_memcpy(p_sw_buffer, (uint8*)temp_dma_memory+tmp_entry_index*entry_offset, entry_size);
                ++entry_id;
            }while(++tmp_entry_index < copy_entry_num[loop]);
            p_sdb->desc_index_map[loop] = DRV_SDB_DMA_INVALID_DESC_IDX;
        }
    }
error_rollback:
    return ret;
}

STATIC int32
_drv_sdb_restore_dynamic(uint8 lchip, drv_sdb_t* p_sdb)
{
    uint8 mem_id = 0;
    uint8 pp_base = drv_vchip_get_pp_base(lchip);
    uint32 sram_tbl_a[200] = {0};
    uint8  share_tbl_num  = 0;
    uint8  per_tbl_entry_num = 0;
    uint32 sram_type = 0;
    uint8 tbl_type = 0; /* 0: PP->core 1: core 2: other */
    uint8 oper_bmp = 0;

    for (mem_id = 0 ; mem_id < DRV_FTM_MAX_ID; mem_id++ )
    {
        if (mem_id < DRV_FTM_EDRAM_MAX)
        {
            sram_type = drv_usw_ftm_memid_2_table(lchip, mem_id);
            drv_usw_ftm_get_sram_tbl_id(lchip, sram_type, sram_tbl_a, &share_tbl_num, &per_tbl_entry_num);
            tbl_type = ((TABLE_ENTRY_TYPE(lchip, sram_tbl_a[0]) == DRV_FEATURE_MODE_PER_CORE)? 1:\
                       ((DRV_TBL_FEA_MOD(sram_tbl_a[0]) == DRV_FEATURE_MODE_PER_CORE)? 0:2));
        }
        else if (mem_id < DRV_FTM_TCAM_AD4)
        {
            tbl_type = ((DRV_TBL_FEA_MOD(DsTunnelId0Tcam_t) == DRV_FEATURE_MODE_PER_CORE)? 0:2);
        }
        else if (mem_id < DRV_FTM_TCAM_AD40)
        {
            tbl_type = ((DRV_TBL_FEA_MOD(DsAcl0Ingress_t) == DRV_FEATURE_MODE_PER_CORE)? 0:2);
        }
        else if (mem_id < DRV_FTM_TCAM_ADM)
        {
            tbl_type = ((DRV_TBL_FEA_MOD(DsEgressScl0TcamAd_t) == DRV_FEATURE_MODE_PER_CORE)? 0:2);
        }
        else
        {
            tbl_type = ((DRV_TBL_FEA_MOD(DsLpmTcamIpv6DoubleKey0Ad_t) == DRV_FEATURE_MODE_PER_CORE)? 0:2);
        }
        if (!tbl_type)
        {
            oper_bmp = p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1] | p_drv_master[lchip]->pp_bmp[g_drv_chip[lchip].pp_id];
            if (lchip != pp_base)
            {
                continue;
            }
        }
        else if (1 == tbl_type)
        {
            oper_bmp = p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1];
            if ((lchip != pp_base) && (lchip != pp_base + p_drv_master[lchip]->core_pp_num))
            {
                continue;
            }
        }
        else
        {
            oper_bmp = p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1] | p_drv_master[lchip]->pp_bmp[g_drv_chip[lchip].pp_id];
        }
        /*Since the table address may not be consecutive*/
        if(p_drv_master[lchip]->p_mem_info[mem_id].index_map || \
            (NULL == p_sdb->dma_read_cb) || (NULL == p_sdb->dma_wait_done_cb))
        {
            if (mem_id >= DRV_FTM_SRAM47 && mem_id <= DRV_FTM_SRAM54)
            {
                /* DP 0 */
                oper_bmp = (oper_bmp & (~(3))) | 1;
                DRV_IF_ERROR_RETURN(_drv_sdb_restore_per_ram_by_io(lchip, mem_id, oper_bmp));
                /* DP 1 */
                oper_bmp = (oper_bmp & (~(3))) | 2;
                DRV_IF_ERROR_RETURN(_drv_sdb_restore_per_ram_by_io(lchip, mem_id, oper_bmp));
            }
            else
            {
                DRV_IF_ERROR_RETURN(_drv_sdb_restore_per_ram_by_io(lchip, mem_id, oper_bmp));
            }
        }
        else
        {
            if (mem_id >= DRV_FTM_SRAM47 && mem_id <= DRV_FTM_SRAM54)
            {
                /* DP 0 */
                oper_bmp = (oper_bmp & (~(3))) | 1;
                DRV_IF_ERROR_RETURN(_drv_sdb_restore_per_ram_by_dma(lchip, mem_id, oper_bmp));
                /* DP 1 */
                oper_bmp = (oper_bmp & (~(3))) | 2;
                DRV_IF_ERROR_RETURN(_drv_sdb_restore_per_ram_by_dma(lchip, mem_id, oper_bmp));
            }
            else
            {
                DRV_IF_ERROR_RETURN(_drv_sdb_restore_per_ram_by_dma(lchip, mem_id, oper_bmp));
            }
        }
    }
    
    return DRV_E_NONE;
}

STATIC int32
_drv_sdb_restore_from_hw(uint8 lchip, drv_sdb_t* p_sdb)
{
    int32 ret = DRV_E_NONE;

    /*static tbl recover: based on tbl_id*/
    DRV_IF_ERROR_RETURN(_drv_sdb_restore_static(lchip, p_sdb));
    DRV_IF_ERROR_RETURN(_drv_sdb_restore_dynamic(lchip, p_sdb));

    /*Since dma has been reinit, reset dma mem index and desc index map to default value*/
    p_sdb->dma_mem_idx = 0;
    sal_memset(p_sdb->desc_index_map, 0xFF, sizeof(p_sdb->desc_index_map));

    /*DRV_DBG_INFO("\n[DB]pass \n");*/
    return ret;
}
#endif
void*
drv_sdb_read(uint8 lchip, tbls_id_t tbl_id, uint32 index, uint32 entry_size, uint8 oper_bmp)
{
    uint32 tbl_max_size = 0;

    if ((2 == (oper_bmp&0x3)) && (p_drv_master[lchip]->dev_type >= DRV_ARCTIC))
    {
#if (SDB_TIMESTAMP == SDB_MODE)
        tbl_max_size = TABLE_MAX_INDEX(lchip, tbl_id) * entry_size + (TABLE_MAX_INDEX(lchip, tbl_id) * DRV_SDB_TS_SIZE);
#else
        tbl_max_size = TABLE_MAX_INDEX(lchip, tbl_id) * entry_size;
#endif
    }

    return ((uint8*)DRV_SDB_ADDR_BASE(tbl_id) + index * entry_size + tbl_max_size);
}

int32
_drv_sdb_sync_table(uint8 lchip, drv_sdb_t* p_sdb);

int32
drv_sdb_set_init_done(uint8 lchip)
{
    int32 ret = 0;
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    drv_sdb_mem_hdr_t* p_mem_hdr = NULL;
    uint8 pp_id = 0;
    dal_dma_info_t dma_info;
    
    if(NULL == p_sdb)
    {
        return DRV_E_NONE;
    }
    if (p_sdb->pmem_en)
    {
        p_mem_hdr = (drv_sdb_mem_hdr_t*)p_sdb->mem_addr;
        p_mem_hdr->wb_version = DRV_WB_VERSION_SDB;
    }

    if (DRV_SDB_WB_RELOADING(lchip) && (0 == p_sdb->restore_tbl_from_hw))
    {
        return DRV_E_NONE;
    }

    /*support not init dma without dma memory*/
    sal_memset(&dma_info, 0 ,sizeof(dal_dma_info_t));
    dal_get_dma_info(DRV_MAP_LDEV(lchip), &dma_info);

#if defined (CTC_HW_RESET_EN) || defined (WARMBOOT)
    if(g_dal_op.dma_alloc && dma_info.size && (lchip == drv_vchip_get_pp_base(lchip)))
    {
        uint16 loop;
        for(loop=0; loop < DRV_SDB_DMA_BUCKET_NUM; loop++)
        {
            if(NULL == (p_sdb->dma_mem_bucket[loop] = g_dal_op.dma_alloc(DRV_MAP_LDEV(lchip), DRV_SDB_MAX_DMA_SIZE(lchip), 0)))
            {
                ret = DRV_E_NO_MEMORY;
                goto error_proc;
            }
        }
    }
#endif

    for (pp_id = lchip; pp_id < (lchip + p_drv_master[lchip]->core_pp_num); pp_id++)
    {
        p_sdb = g_sdb_master[pp_id];
#if (SDB_TIMESTAMP == SDB_MODE)
        ((drv_sdb_mem_hdr_t*)p_sdb->mem_addr)->init_done = 1;
#endif

#if SDK_WORK_PLATFORM == 0
        if (0 == p_sdb->restore_tbl_from_hw)
        {
            _drv_sdb_sync_table(pp_id, p_sdb);
        }

        if (1 == p_sdb->restore_tbl_from_hw)
        {
            _drv_sdb_restore_from_hw(pp_id, p_sdb);
            p_sdb->restore_tbl_from_hw = 0;
        }
        p_sdb->read_tbl_from_hw = 0;
#endif
    }

    return ret;
#if defined (CTC_HW_RESET_EN) || defined (WARMBOOT)
error_proc:
    if(g_dal_op.dma_free && (lchip == drv_vchip_get_pp_base(lchip)))
    {
        uint16 loop;
        for(loop=0; loop < DRV_SDB_DMA_BUCKET_NUM; loop++)
        {
            if(p_sdb->dma_mem_bucket[loop])
            {
                g_dal_op.dma_free(DRV_MAP_LDEV(lchip), p_sdb->dma_mem_bucket[loop]);
            }
        }
    }
    return ret;
#endif
}

void
drv_sdb_get_table_enable(uint8 lchip, uint32 tbl_id, uint8* enable)
{
    if (0 == TABLE_INFO(lchip, tbl_id).field_num || !DRV_SDB_MODE_VALID(tbl_id) || 0 == DRV_SDB_ADDR_BASE(tbl_id))
    {
        *enable = FALSE;
    }
    else
    {
        *enable = TRUE;
    }
}

int32
_drv_sdb_sync_table(uint8 lchip, drv_sdb_t* p_sdb)
{
#define DRV_SDB_SYNC(tbl_id)    tbl_id,
    int32  ret = 0;
    uint32 cmd = 0;
    uint8 oper_bmp = 0;
    uint32 tbl_id = 0, tbl_id_idx = 0;
    uint32 index = 0;
    uint32 drv_ds_t[36];
    uint8 pp_base = drv_vchip_get_pp_base(lchip);
    static uint32 sync_tbl_id[] = {
        #include "usw/include/drv_sdb_sync_table.h"
        MaxTblId_t
    };
    DRV_IOCTL_CB drv_ioctl_cb = p_drv_master[lchip]->ioctl_cb[DRV_TBL_TYPE_NORMAL][DRV_IOC_READ];
    p_sdb->read_tbl_from_hw = TRUE;
    do {
        tbl_id = sync_tbl_id[tbl_id_idx];
        if ((lchip != pp_base) && (lchip != pp_base + p_drv_master[lchip]->core_pp_num) && TABLE_ENTRY_TYPE(lchip, tbl_id) == DRV_FEATURE_MODE_PER_CORE)
        {
            continue;
        }
        else if (lchip != pp_base && DRV_TBL_FEA_MOD(tbl_id) == DRV_FEATURE_MODE_PER_CORE && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_CORE)
        {
            continue;
        }
        if (0 == TABLE_FIELD_NUM(lchip, tbl_id) || TABLE_ENTRY_SIZE(lchip, tbl_id) > sizeof(drv_ds_t) || 0 == DRV_SDB_MODE(tbl_id))
        {
            /*DRV_SDB_DUMP("  size over ds:table(%s)\n", TABLE_NAME(lchip, tbl_id));*/
            continue;
        }

        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        index = 0;
        do {
            oper_bmp = (p_drv_master[lchip]->core_bmp[g_drv_chip[lchip].core_id][1]|p_drv_master[lchip]->pp_bmp[g_drv_chip[lchip].pp_id]|1)&
                       (p_drv_master[lchip]->oper_mask[TABLE_ENTRY_TYPE(lchip, tbl_id)]);
            ret = drv_ioctl_cb(lchip, index, cmd, oper_bmp, drv_ds_t);
            if (ret != 0)
            {
                /*DRV_SDB_DUMP("  sync table(%s) error!!!\n", TABLE_NAME(lchip, tbl_id))*/
                continue;
            }
            drv_sdb_store(lchip, tbl_id, index, drv_ds_t, TABLE_ENTRY_SIZE(lchip, tbl_id), 0);

            if ((p_drv_master[lchip]->dev_type < DRV_ARCTIC) || 
                (TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_DP && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PEER_DP))
            {
                continue;
            }

            /* DP1 */
            oper_bmp = (oper_bmp & (~(3))) | 2;
            ret = drv_ioctl_cb(lchip, index, cmd, oper_bmp, drv_ds_t);
            if (ret != 0)
            {
                /*DRV_SDB_DUMP("  sync table(%s) error!!!\n", TABLE_NAME(lchip, tbl_id))*/
                continue;
            }
            drv_sdb_store(lchip, tbl_id, index, drv_ds_t, TABLE_ENTRY_SIZE(lchip, tbl_id), 1);
        }while(++index < TABLE_MAX_INDEX(lchip, tbl_id));
    }while(++tbl_id_idx < sizeof(sync_tbl_id)/sizeof(uint32)-1);
    p_sdb->read_tbl_from_hw = FALSE;

    return DRV_E_NONE;
}

#define __SDB_TBL_CLASS_START
int32
drv_sdb_set_tbl_feature_mode(uint8 lchip, uint32 tbl_id, uint8 mode)
{
    DRV_INIT_CHECK(lchip);
    DRV_TBL_FEA_MOD(tbl_id) = mode;
    return 0;
}
#define __SDB_TBL_CLASS_END

int32
drv_sdb_init(uint8 lchip , void* p_cfg_temp)
{
#if (SDB_DISABLE != SDB_MODE)
    uint32 total_tbl_size = 0;
    uint32 mem_offset = 0;
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
#if (SDB_TIMESTAMP == SDB_MODE)
    uint32* p_data_memory = NULL;
#endif
    drv_ser_global_cfg_t* p_cfg = p_cfg_temp;
    drv_sdb_mem_hdr_t*    p_mem_hdr = NULL;
    uint8 pmem_dis = 0;
    uint8 pp_base = drv_vchip_get_pp_base(lchip);
    uint8 pp_num = drv_vchip_get_pp_num(lchip);
    uint8 index = 0;

    DRV_PTR_VALID_CHECK(p_cfg);

    if (!p_cfg->sdb_en || 0 == p_cfg->sdb_type) /*sdb disable*/
    {
        return DRV_E_NONE;
    }

    if (p_cfg->sdb_type > SDB_ALL)
    {
        DRV_DUMP_INFO("  [SDB] Init fail! Invalid sdb_type(%u)\n", p_cfg->sdb_type);
        return DRV_E_INIT_FAILED;
    }

    /* 1. init static table */
    {
        if (p_sdb) /*SDB init done*/
        {
            return DRV_E_NONE;
        }
        p_drv_master[lchip]->sdb_type = p_cfg->sdb_type;

        for (index = pp_base; (lchip == pp_base) && (index < pp_base + pp_num); index++) /* check whether global reserved memory is engouh */
        {
            total_tbl_size += drv_sdb_calc_tbl_size(index, 2);
        }

        mem_offset = sizeof(drv_sdb_mem_hdr_t);
        total_tbl_size += sizeof(drv_sdb_mem_hdr_t);

        p_sdb = (drv_sdb_t*)mem_malloc(MEM_SYSTEM_MODULE, sizeof(drv_sdb_t));
        if (!p_sdb)
        {
            DRV_IF_ERROR_RETURN(DRV_E_NO_MEMORY);
        }
        sal_memset(p_sdb, 0, sizeof(drv_sdb_t));
        g_sdb_master[lchip] = p_sdb;
        p_sdb->read_tbl_from_hw = 1;  /*SDK init process, default set read from hw */

        if (lchip != pp_base)
        {
            p_sdb->pmem_en = g_sdb_master[pp_base]->pmem_en;
        }
        else
        {
            if (p_cfg->mem_size < total_tbl_size || !p_cfg->mem_addr)
            {
                DRV_DUMP_INFO("[SDB] Reserved memory is invalid! SDB will alloc dynamic memory to store data!\n"); 
                pmem_dis = 1;
            }
            else if (DRV_SDB_WB_RELOADING(lchip))
            {            
                p_mem_hdr = (drv_sdb_mem_hdr_t*)p_cfg->mem_addr;     
                if (DRV_WB_VERSION_CHECK(DRV_WB_VERSION_SDB, p_mem_hdr->wb_version))
                {
                    DRV_DUMP_INFO("[SDB] WB Version not match, Old(%X) -> New(%X)!\n", p_mem_hdr->wb_version, DRV_WB_VERSION_SDB);                
                    pmem_dis = 1;
                }
            }
            p_sdb->pmem_en = !pmem_dis;
        }


        if (!p_sdb->pmem_en)
        {
#if (SDB_TIMESTAMP == SDB_MODE)
            p_data_memory = mem_malloc(MEM_SYSTEM_MODULE, sizeof(drv_sdb_mem_hdr_t));
            if (!p_data_memory)
            {
                mem_free(p_sdb);
                return DRV_E_NO_MEMORY;
            }
            sal_memset(p_data_memory, 0, sizeof(drv_sdb_mem_hdr_t));
            p_sdb->mem_addr = (uintptr)p_data_memory;
#endif
            p_sdb->mem_size = total_tbl_size;
            p_sdb->restore_tbl_from_hw = DRV_SDB_WB_RELOADING(lchip)?1:0;
        }
        else
        {
            p_sdb->mem_addr = p_cfg->mem_addr;
            p_sdb->mem_size = p_cfg->mem_size;
            if (lchip == pp_base)
            {
                if (!DRV_SDB_WB_RELOADING(lchip))
                {
                    sal_memset((uint8*)p_cfg->mem_addr, 0, p_cfg->mem_size);
                }
            }
            else
            {
                for (index=pp_base; index < lchip; index++)
                {
                    p_sdb->mem_addr += (g_sdb_master[index]->catch_mem_static_size + g_sdb_master[index]->catch_mem_dynamic_size);
                }
            }
            if (DRV_SDB_WB_RELOADING(lchip))
            {
                p_sdb->read_tbl_from_hw = 0;
            }
        }
        p_sdb->sdb_en   =  p_cfg->sdb_en;
        
        DRV_IF_ERROR_RETURN(_drv_sdb_init_static_tbl(lchip, &mem_offset, p_cfg, p_sdb->pmem_en));
        p_sdb->catch_mem_static_size = mem_offset;
    }

    /* 2. init dynamic table */
    {
        mem_offset = p_sdb->catch_mem_static_size;
        DRV_IF_ERROR_RETURN(_drv_sdb_init_dynamic_tbl(lchip, &mem_offset, p_sdb->pmem_en));
    }

    sal_memset(p_sdb->desc_index_map, 0xFF, sizeof(p_sdb->desc_index_map));
#endif
    return DRV_E_NONE;
}

int32
drv_sdb_get_tbl_by_ram(uint8 lchip, uint32 ram_id)
{
    uint32 tbl_id = 0;
    uint32 sram_id = 0;
    uint32 sram_offset = 0;
    uint16 vari_tbl[120] = {0};
    uint8 index = 0;
    uint8 is_first = 1;
    uint8 tbl_type = 0;
    uint8 fea_mod = 0;

    if (!p_drv_master[lchip] || !(p_drv_master[lchip]->dev_type >= DRV_ARCTIC))
    {
        return DRV_E_NONE;
    }

    for (; tbl_id< MaxTblId_t; tbl_id++)
    {
        tbl_type = _drv_sdb_get_tbl_type(lchip, tbl_id);
        DRV_SDB_IF_CONTINUE(tbl_type == DRV_FTM_TABLE_STATIC);
        DRV_SDB_IF_CONTINUE(!DRV_SDB_MODE_VALID(tbl_id));
        drv_usw_ftm_table_id_2_mem_id(lchip, tbl_id, 0, &sram_id, &sram_offset);
        if (sram_id == ram_id)
        {
            DRV_SDB_DUMP("%d %s\n", tbl_id, TABLE_NAME(lchip, tbl_id));
            if (is_first)
            {
                fea_mod = DRV_TBL_FEA_MOD(tbl_id);
                is_first = 0;
            }
            else
            {
                if (fea_mod != DRV_TBL_FEA_MOD(tbl_id))
                {
                    vari_tbl[index++] = tbl_id;
                }
            }
        }
    }
    for (tbl_id = 0; vari_tbl[tbl_id]; tbl_id++)
    {
        DRV_SDB_DUMP("fea mode %d, variant tbl %s\n", fea_mod, TABLE_NAME(lchip, vari_tbl[tbl_id]));
    }

    return DRV_E_NONE;
}

int32
drv_sdb_get_vari_tbl(uint8 lchip)
{
    uint32 tbl_id = 0;

    if (!g_sdb_master[lchip] || !p_drv_master[lchip])
    {
        return DRV_E_NONE;
    }

    for (; tbl_id< MaxTblId_t; tbl_id++)
    {
        if (DRV_SDB_ADDR_BASE(tbl_id) && (DRV_TBL_FEA_MOD(tbl_id) != TABLE_ENTRY_TYPE(lchip, tbl_id)))
        {
            DRV_SDB_DUMP("%s\n", TABLE_NAME(lchip, tbl_id));
        }
    }

    return DRV_E_NONE;
}

int32
drv_sdb_get_tbl_size(uint8 lchip, uint32 tbl_id)
{
    struct mem_block_header* mhdr;

    if (tbl_id > MaxTblId_t || !g_sdb_master[lchip] || !p_drv_master[lchip] || g_sdb_master[lchip]->pmem_en)
    {
        return DRV_E_NONE;
    }

    if (tbl_id == MaxTblId_t)
    {
        for (tbl_id = 0; tbl_id< MaxTblId_t; tbl_id++)
        {
            if (DRV_SDB_MODE_VALID(tbl_id) && DRV_SDB_ADDR_BASE(tbl_id))
            {
                mhdr = (struct mem_block_header *)(DRV_SDB_ADDR_BASE(tbl_id) -sizeof(struct mem_block_header));
                if (mhdr->req_size)
                {
                    DRV_SDB_DUMP("tbl (%d, %s), size %u\n", tbl_id, TABLE_NAME(lchip, tbl_id), mhdr->req_size);
                }
            }
        }
    }
    else
    {
        if (DRV_SDB_MODE_VALID(tbl_id) && DRV_SDB_ADDR_BASE(tbl_id))
        {
#if (SDB_TIMESTAMP == SDB_MODE)
            mhdr = (struct mem_block_header *)(DRV_SDB_ADDR_BASE(tbl_id) - sizeof(drv_sdb_ts_hdr_t) - sizeof(struct mem_block_header));
#else
            mhdr = (struct mem_block_header *)(DRV_SDB_ADDR_BASE(tbl_id) -sizeof(struct mem_block_header));
#endif
            if (mhdr->req_size)
            {
                DRV_SDB_DUMP("tbl (%d, %s), size %u\n", tbl_id, TABLE_NAME(lchip, tbl_id), mhdr->req_size);
            }
        }
    }

    return DRV_E_NONE;
}


int32
drv_sdb_deinit(uint8 lchip)
{
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
#if (SDB_TIMESTAMP == SDB_MODE)
    uint32* p_data_memory = NULL;
#endif
    uint32 tbl_id = 0;
    uint32 dyn_mem_bmp[(DRV_FTM_MAX_ID+31)/32] = {0};
    uint32 sram_id = 0;
    uint32 sram_offset = 0;
    uint8 pp_base = drv_vchip_get_pp_base(lchip);

    if (!p_sdb)
    {
        return DRV_E_NONE;
    }

    if (p_sdb->pmem_en == 0)
    {
        for (tbl_id = 0; tbl_id < MaxTblId_t; tbl_id++ )
        {
            if ((lchip != pp_base) && (lchip != pp_base + p_drv_master[lchip]->core_pp_num) && TABLE_ENTRY_TYPE(lchip, tbl_id) == DRV_FEATURE_MODE_PER_CORE)
            {
                continue;
            }
            else if (lchip != pp_base && DRV_TBL_FEA_MOD(tbl_id) == DRV_FEATURE_MODE_PER_CORE && TABLE_ENTRY_TYPE(lchip, tbl_id) != DRV_FEATURE_MODE_PER_CORE)
            {
                continue;
            }
            tbl_id = (((DsNeoLpmIpv4Bit32Snake1_t == tbl_id) && ((p_drv_master[lchip]->dev_type == DRV_TSINGMA_MX) || (p_drv_master[lchip]->dev_type == DRV_TSINGMA_GX)))? DsNeoLpmIpv4Bit32Snake_t: tbl_id);
            DRV_SDB_IF_CONTINUE(0 == TABLE_MAX_INDEX(lchip, tbl_id));
#if (SDB_TIMESTAMP == SDB_MODE)
            if (DRV_SDB_ADDR_BASE(tbl_id))
            {
                DRV_SDB_ADDR_BASE(tbl_id) -= sizeof(drv_sdb_ts_hdr_t);
            }
#endif
            if (DRV_FTM_TABLE_STATIC == _drv_sdb_get_tbl_type(lchip, tbl_id))
            {
                mem_free(DRV_SDB_ADDR_BASE(tbl_id));
            }
            else
            {
                drv_usw_ftm_table_id_2_mem_id(lchip, tbl_id, 0, &sram_id, &sram_offset);
                if (DRV_BMP_ISSET(dyn_mem_bmp, sram_id))
                {
                    continue;
                }
                if (DRV_SDB_ADDR_BASE(tbl_id))
                {
                    mem_free(DRV_SDB_ADDR_BASE(tbl_id));
                    DRV_BMP_SET(dyn_mem_bmp, sram_id);
                }
            }
        }
#if (SDB_TIMESTAMP == SDB_MODE)
        p_data_memory = (uint32*)p_sdb->mem_addr;
        mem_free(p_data_memory);
#endif
    }
#if defined (CTC_HW_RESET_EN) || defined (WARMBOOT)
    if(g_dal_op.dma_free && (lchip == pp_base))
    {
        uint8  loop;
        for(loop=0; loop < DRV_SDB_DMA_BUCKET_NUM; loop++)
        {
            if(p_sdb->dma_mem_bucket[loop])
            {
                g_dal_op.dma_free(DRV_MAP_LDEV(lchip), p_sdb->dma_mem_bucket[loop]);
            }
        }
    }
#endif
    mem_free(g_sdb_master[lchip]);
    return DRV_E_NONE;
}
uint32 drv_sdb_get_sdb_en(uint8 lchip)
{
    if (lchip >= DRV_MAX_CHIP_NUM || !p_drv_master[lchip] || !p_drv_master[lchip]->init_done || !g_sdb_master[lchip])
    {
        return 0;
    }
    return ((drv_sdb_t*)g_sdb_master[lchip])->sdb_en;
}
extern int32
drv_sdb_register_dma_write_cb(uint8 lchip, DRV_DMA_WRITE_CB cb)
{
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    if (!p_sdb)
    {
        return DRV_E_NONE;
    }

    p_sdb->dma_write_cb = cb;
    return DRV_E_NONE;
}

int32
drv_sdb_register_dma_read_cb(uint8 lchip, DRV_DMA_READ_CB cb)
{
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    if (!p_sdb)
    {
        return DRV_E_NONE;
    }

    p_sdb->dma_read_cb = cb;
    return DRV_E_NONE;
}


extern int32
drv_sdb_register_dma_wait_done_cb(uint8 lchip, DRV_DMA_WAIT_DESC_DONE_CB cb)
{
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    if (!p_sdb)
    {
        return DRV_E_NONE;
    }

    p_sdb->dma_wait_done_cb = cb;
    return DRV_E_NONE;
}

int32
drv_sdb_register_dma_trigger_cb(uint8 lchip, DRV_DMA_TRIGGER_CB cb)
{
    drv_sdb_t* p_sdb = g_sdb_master[lchip];
    if (!p_sdb)
    {
        return DRV_E_NONE;
    }

    p_sdb->dma_trigger_cb = cb;
    return DRV_E_NONE;
}
